Maintain invariant that a specialization can only exist if there is only one support bit
[hiphop-php.git] / hphp / hhbbc / test / type-system.cpp
blob7cc58494e2763f412338340f1800c1c2e27c06b3
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
16 #include "hphp/hhbbc/type-system.h"
18 #include <gtest/gtest.h>
19 #include <boost/range/join.hpp>
20 #include <algorithm>
21 #include <limits>
22 #include <memory>
23 #include <utility>
24 #include <vector>
26 #include <folly/Lazy.h>
28 #include "hphp/runtime/base/array-init.h"
30 #include "hphp/hhbbc/context.h"
31 #include "hphp/hhbbc/hhbbc.h"
32 #include "hphp/hhbbc/misc.h"
33 #include "hphp/hhbbc/representation.h"
34 #include "hphp/hhbbc/parse.h"
35 #include "hphp/hhbbc/type-structure.h"
36 #include "hphp/hhbbc/index.h"
37 #include "hphp/runtime/base/tv-comparisons.h"
38 #include "hphp/runtime/vm/as.h"
39 #include "hphp/runtime/vm/native.h"
40 #include "hphp/runtime/vm/unit-emitter.h"
42 namespace HPHP::HHBBC {
44 void PrintTo(const Type& t, ::std::ostream* os) { *os << show(t); }
45 void PrintTo(Emptiness e, ::std::ostream* os) {
46 switch (e) {
47 case Emptiness::Empty: *os << "empty"; break;
48 case Emptiness::NonEmpty: *os << "non-empty"; break;
49 case Emptiness::Maybe: *os << "maybe"; break;
50 default: always_assert(false);
54 Type make_obj_for_testing(trep, res::Class, bool, bool, bool);
55 Type make_cls_for_testing(trep, res::Class, bool, bool, bool);
56 Type make_arrval_for_testing(trep, SArray);
57 Type make_arrpacked_for_testing(trep, std::vector<Type>);
58 Type make_arrpackedn_for_testing(trep, Type);
59 Type make_arrmap_for_testing(trep, MapElems, Type, Type);
60 Type make_arrmapn_for_testing(trep, Type, Type);
62 namespace {
64 //////////////////////////////////////////////////////////////////////
66 const StaticString s_test("test");
67 const StaticString s_TestClass("TestClass");
68 const StaticString s_Base("Base");
69 const StaticString s_A("A");
70 const StaticString s_AA("AA");
71 const StaticString s_AB("AB");
72 const StaticString s_B("B");
73 const StaticString s_BA("BA");
74 const StaticString s_BB("BB");
75 const StaticString s_BAA("BAA");
76 const StaticString s_C("C");
77 const StaticString s_IBase("IBase");
78 const StaticString s_IA("IA");
79 const StaticString s_IAA("IAA");
80 const StaticString s_IB("IB");
82 const StaticString s_I_A("I_A");
83 const StaticString s_I_B("I_B");
84 const StaticString s_I_C("I_C");
85 const StaticString s_I_D("I_D");
86 const StaticString s_I_E("I_E");
87 const StaticString s_I_F("I_F");
88 const StaticString s_I_G("I_G");
89 const StaticString s_I_H("I_H");
90 const StaticString s_I_I("I_I");
91 const StaticString s_I_J("I_J");
92 const StaticString s_I_K("I_K");
94 const StaticString s_X1("X1");
95 const StaticString s_X2("X2");
96 const StaticString s_X3("X3");
97 const StaticString s_X4("X4");
98 const StaticString s_X5("X5");
99 const StaticString s_X6("X6");
100 const StaticString s_X7("X7");
101 const StaticString s_X8("X8");
102 const StaticString s_X9("X9");
103 const StaticString s_X10("X10");
104 const StaticString s_X11("X11");
105 const StaticString s_X12("X12");
106 const StaticString s_X13("X13");
107 const StaticString s_X14("X14");
108 const StaticString s_X15("X15");
109 const StaticString s_X16("X16");
110 const StaticString s_X17("X17");
111 const StaticString s_X18("X18");
112 const StaticString s_X19("X19");
113 const StaticString s_X20("X20");
114 const StaticString s_X21("X21");
115 const StaticString s_X22("X22");
116 const StaticString s_X23("X23");
117 const StaticString s_X24("X24");
118 const StaticString s_X25("X25");
119 const StaticString s_X26("X26");
120 const StaticString s_X27("X27");
121 const StaticString s_X28("X28");
122 const StaticString s_X29("X29");
124 const StaticString s_Y1("Y1");
125 const StaticString s_Y2("Y2");
126 const StaticString s_Y3("Y3");
127 const StaticString s_Y4("Y4");
128 const StaticString s_Y5("Y5");
129 const StaticString s_Y6("Y6");
130 const StaticString s_Y7("Y7");
131 const StaticString s_Y8("Y8");
132 const StaticString s_Y9("Y9");
134 const StaticString s_IY1("I_Y1");
135 const StaticString s_IY2("I_Y2");
136 const StaticString s_IY3("I_Y3");
138 const StaticString s_IZ1("I_Z1");
139 const StaticString s_IZ2("I_Z2");
140 const StaticString s_IZ3("I_Z3");
141 const StaticString s_IZ4("I_Z4");
142 const StaticString s_IZ5("I_Z5");
143 const StaticString s_IZ6("I_Z6");
145 const StaticString s_Z1("Z1");
146 const StaticString s_Z2("Z2");
147 const StaticString s_Z3("Z3");
148 const StaticString s_Z4("Z4");
149 const StaticString s_Z5("Z5");
150 const StaticString s_Z6("Z6");
151 const StaticString s_Z7("Z7");
152 const StaticString s_Z8("Z8");
153 const StaticString s_Z9("Z9");
154 const StaticString s_Z10("Z10");
156 const StaticString s_ICanon1("ICanon1");
157 const StaticString s_ICanon2("ICanon2");
158 const StaticString s_ICanon3("ICanon3");
159 const StaticString s_ICanon4("ICanon4");
160 const StaticString s_ICanon5("ICanon5");
161 const StaticString s_ICanon6("ICanon6");
162 const StaticString s_Canon3("Canon3");
164 const StaticString s_Awaitable("HH\\Awaitable");
166 // Deliberately doesn't exist
167 const StaticString s_Foo1("Foo1");
168 const StaticString s_Foo2("Foo2");
170 // A test program so we can actually test things involving object or
171 // class types.
172 void add_test_unit(php::Program& program) {
173 assertx(SystemLib::s_inited);
174 std::string const hhas = R"(
175 # Technically this should be provided by systemlib, but it's the
176 # only one we have to make sure the type system can see for unit
177 # test purposes, so we can just define it here. We don't need to
178 # give it any of its functions currently.
179 .class [abstract unique builtin] HH\Awaitable {
182 .class [unique builtin] HH\AwaitableChild extends HH\Awaitable {
185 .class [interface unique] IBase {
188 .class [interface unique] IA implements (IBase) {
191 .class [interface unique] IB implements (IBase) {
194 .class [interface unique] IAA implements (IA) {
197 .class [unique] Base {
198 .default_ctor;
201 .class [unique] A extends Base implements (IA) {
202 .default_ctor;
205 .class [no_override unique] AA extends A implements (IAA) {
206 .default_ctor;
209 .class [no_override unique] AB extends A {
210 .default_ctor;
213 .class [unique] B extends Base {
214 .default_ctor;
217 .class [unique] BA extends B {
218 .default_ctor;
221 .class [no_override unique] BB extends B {
222 .default_ctor;
225 .class [unique] BAA extends BA {
226 .default_ctor;
229 # Make sure BAA doesn't get AttrNoOverride:
230 .class [unique] BAADeriver extends BAA {
231 .default_ctor;
234 .class [unique] TestClass {
235 .default_ctor;
238 # Make sure TestClass doesn't get AttrNoOverride:
239 .class [unique] TestClassDeriver extends TestClass {
240 .default_ctor;
243 .class [interface unique] I_A {
245 .class [interface unique] I_B {
247 .class [interface unique] I_C {
249 .class [interface unique] I_D {
251 .class [interface unique] I_E {
253 .class [interface unique] I_F {
255 .class [interface unique] I_G {
257 .class [interface unique] I_H {
259 .class [interface unique] I_I {
261 .class [interface unique] I_J {
263 .class [interface unique] I_K {
266 .class [unique] X1 {
268 .class [unique] X2 extends X1 implements (I_A) {
270 .class [unique] X3 extends X1 implements (I_B) {
272 .class [unique] X4 extends X1 implements (I_C) {
274 .class [unique] X5 extends X1 implements (I_D) {
276 .class [unique] X6 extends X2 implements (I_E) {
278 .class [unique] X7 extends X6 implements (I_I) {
280 .class [unique] X8 extends X6 implements (I_J) {
282 .class [unique] X9 extends X5 implements (I_I) {
284 .class [unique] X10 extends X2 implements (I_D) {
286 .class [unique] X11 extends X10 implements (I_I) {
288 .class [unique] X12 extends X2 implements (I_F) {
290 .class [unique] X13 extends X12 implements (I_J) {
292 .class [unique] X14 extends X2 implements (I_J) {
294 .class [unique] X15 extends X2 implements (I_G) {
296 .class [unique] X16 extends X1 implements (I_G) {
298 .class [unique] X17 extends X3 implements (I_G) {
300 .class [unique] X18 extends X3 implements (I_H) {
302 .class [unique] X19 extends X3 implements (I_K) {
304 .class [unique] X20 extends X1 implements (I_K) {
306 .class [unique] X21 {
308 .class [unique] X22 extends X21 implements (I_A) {
310 .class [unique] X23 extends X21 implements (I_B) {
312 .class [unique] X24 extends X21 implements (I_C) {
314 .class [unique] X25 extends X21 implements (I_E) {
316 .class [unique] X26 extends X21 implements (I_F) {
318 .class [unique] X27 extends X21 implements (I_H) {
320 .class [unique] X28 extends X21 {
322 .class [unique] X29 extends X1 {
325 .class [interface unique] I_Y1 {
327 .class [interface unique] I_Y2 {
329 .class [interface unique] I_Y3 {
332 .class [unique] Y1 implements (I_Y2 I_Y3) {
334 .class [unique] Y2 extends Y1 {
336 .class [unique] Y3 extends Y1 {
338 .class [unique] Y4 extends Y2 implements (I_Y1) {
340 .class [unique] Y5 extends Y3 implements (I_Y1) {
342 .class [unique] Y6 implements (I_Y2 I_Y3) {
344 .class [unique] Y7 implements (I_Y1 I_Y2 I_Y3) {
346 .class [unique] Y8 implements (I_Y2) {
348 .class [unique] Y9 implements (I_Y3) {
351 .class [interface unique] I_Z1 {
353 .class [interface unique] I_Z2 {
355 .class [interface unique] I_Z3 {
357 .class [interface unique] I_Z4 {
359 .class [interface unique] I_Z5 {
361 .class [interface unique] I_Z6 {
364 .class [abstract unique] Z1 implements (I_Z2) {
366 .class [unique] Z2 extends Z1 implements (I_Z1) {
368 .class [unique] Z3 extends Z1 implements (I_Z1) {
370 .class [unique] Z4 {
372 .class [abstract unique] Z5 extends Z4 implements (I_Z4) {
374 .class [unique] Z6 extends Z4 implements (I_Z3 I_Z4) {
376 .class [unique] Z7 implements (I_Z5 I_Z6) {
378 .class [unique] Z8 implements (I_Z5 I_Z6) {
380 .class [unique] Z9 implements (I_Z5) {
382 .class [abstract unique] Z10 implements (I_Z6) {
385 .class [interface unique] ICanon1 {
388 .class [interface unique] ICanon2 implements (ICanon1) {
391 .class [interface unique] ICanon3 {
394 .class [interface unique] ICanon4 {
397 .class [interface unique] ICanon5 {
400 .class [interface unique] ICanon6 implements (ICanon5) {
403 .class [unique] Canon1 implements (ICanon3 ICanon4) {
406 .class [unique] Canon2 implements (ICanon3 ICanon4) {
409 .class [unique] Canon3 implements (ICanon6) {
412 .function test() {
413 Int 1
414 RetC
417 std::unique_ptr<UnitEmitter> ue(assemble_string(
418 hhas.c_str(), hhas.size(),
419 "ignore.php",
420 SHA1("1234543212345432123454321234543212345432"),
421 Native::s_noNativeFuncs
423 parse_unit(program, ue.get());
426 php::ProgramPtr make_test_program() {
427 auto program = make_program();
428 add_test_unit(*program);
429 return program;
432 //////////////////////////////////////////////////////////////////////
434 Type make_specialized_string(trep bits, SString s) {
435 return set_trep_for_testing(sval(s), bits);
438 Type make_specialized_lazycls(trep bits, SString s) {
439 return set_trep_for_testing(lazyclsval(s), bits);
442 Type make_specialized_int(trep bits, int64_t i) {
443 return set_trep_for_testing(ival(i), bits);
446 Type make_specialized_double(trep bits, double d) {
447 return set_trep_for_testing(dval(d), bits);
450 Type make_specialized_wait_handle(trep bits, Type inner, const Index& index) {
451 return set_trep_for_testing(wait_handle(index, std::move(inner)), bits);
454 Type make_specialized_exact_object(trep bits, res::Class cls,
455 bool isCtx = false) {
456 return make_obj_for_testing(bits, cls, false, isCtx, false);
459 Type make_specialized_sub_object(trep bits, res::Class cls,
460 bool isCtx = false,
461 bool canonicalize = true) {
462 return make_obj_for_testing(bits, cls, true, isCtx, canonicalize);
465 Type make_specialized_exact_class(trep bits, res::Class cls,
466 bool isCtx = false) {
467 return make_cls_for_testing(bits, cls, false, isCtx, false);
470 Type make_specialized_sub_class(trep bits, res::Class cls,
471 bool isCtx = false,
472 bool canonicalize = true) {
473 return make_cls_for_testing(bits, cls, true, isCtx, canonicalize);
476 Type make_specialized_arrval(trep bits, SArray ar) {
477 return make_arrval_for_testing(bits, ar);
480 Type make_specialized_arrpacked(trep bits,
481 std::vector<Type> elems,
482 Optional<LegacyMark> mark = std::nullopt) {
483 return make_arrpacked_for_testing(bits, std::move(elems), mark);
486 Type make_specialized_arrpackedn(trep bits, Type type) {
487 return make_arrpackedn_for_testing(bits, std::move(type));
490 Type make_specialized_arrmap(trep bits, MapElems elems,
491 Type optKey = TBottom, Type optVal = TBottom,
492 Optional<LegacyMark> mark = std::nullopt) {
493 return make_arrmap_for_testing(
494 bits, std::move(elems), std::move(optKey), std::move(optVal), mark
498 Type make_specialized_arrmapn(trep bits, Type key, Type val) {
499 return make_arrmapn_for_testing(bits, std::move(key), std::move(val));
502 trep get_bits(const Type& t) { return get_trep_for_testing(t); }
504 Type make_unmarked(Type t) {
505 if (!t.couldBe(BVec|BDict)) return t;
506 return set_mark_for_testing(t, LegacyMark::Unmarked);
509 void make_unmarked(std::vector<Type>& types) {
510 for (auto& t : types) t = make_unmarked(std::move(t));
513 //////////////////////////////////////////////////////////////////////
515 Type sval(const StaticString& s) { return HPHP::HHBBC::sval(s.get()); }
516 Type sval_nonstatic(const StaticString& s) {
517 return HPHP::HHBBC::sval_nonstatic(s.get());
519 Type sval_counted(const StaticString& s) {
520 return HPHP::HHBBC::sval_counted(s.get());
523 Type lazyclsval(const StaticString& s) {
524 return HPHP::HHBBC::lazyclsval(s.get());
527 TypedValue tv(SString s) { return make_tv<KindOfPersistentString>(s); }
528 TypedValue tv(const StaticString& s) { return tv(s.get()); }
529 TypedValue tv(int64_t i) { return make_tv<KindOfInt64>(i); }
531 std::pair<TypedValue, MapElem> map_elem(int64_t i, Type t) {
532 return {tv(i), MapElem::IntKey(std::move(t))};
534 std::pair<TypedValue, MapElem> map_elem(SString s, Type t) {
535 return {tv(s), MapElem::SStrKey(std::move(t))};
537 std::pair<TypedValue, MapElem> map_elem(const StaticString& s, Type t) {
538 return {tv(s), MapElem::SStrKey(std::move(t))};
541 std::pair<TypedValue, MapElem> map_elem_nonstatic(const StaticString& s,
542 Type t) {
543 return {tv(s), MapElem::StrKey(std::move(t))};
545 std::pair<TypedValue, MapElem> map_elem_counted(const StaticString& s,
546 Type t) {
547 return {tv(s), MapElem::CStrKey(std::move(t))};
550 template<typename... Args>
551 SArray static_vec(Args&&... args) {
552 auto ar = make_vec_array(std::forward<Args>(args)...);
553 return ArrayData::GetScalarArray(std::move(ar));
556 template<typename... Args>
557 SArray static_dict(Args&&... args) {
558 auto ar = make_dict_array(std::forward<Args>(args)...);
559 return ArrayData::GetScalarArray(std::move(ar));
562 template<typename... Args>
563 SArray static_keyset(Args&&... args) {
564 auto ar = make_keyset_array(std::forward<Args>(args)...);
565 return ArrayData::GetScalarArray(std::move(ar));
568 //////////////////////////////////////////////////////////////////////
570 auto const predefined = folly::lazy([]{
571 std::vector<std::pair<trep, Type>> types{
572 #define X(y, ...) { B##y, T##y },
573 HHBBC_TYPE_PREDEFINED(X)
574 #undef X
576 types.emplace_back(BInt|BObj, Type{BInt|BObj});
577 types.emplace_back(BKeysetN|BVecN, Type{BKeysetN|BVecN});
578 types.emplace_back(BKeysetN|BDictN, Type{BKeysetN|BDictN});
579 types.emplace_back(BKeysetE|BVecE, Type{BKeysetE|BVecE});
580 types.emplace_back(BKeysetE|BDictE, Type{BKeysetE|BDictE});
581 return types;
584 auto const optionals = folly::lazy([]{
585 std::vector<Type> opts;
586 for (auto const& p : predefined()) {
587 if (p.first == BTop) continue;
588 if (!couldBe(p.first, BInitNull) || subtypeOf(p.first, BInitNull)) continue;
589 opts.emplace_back(p.second);
591 return opts;
594 // In the sense of "non-union type", not the sense of TPrim.
595 auto const primitives = folly::lazy([]{
596 return std::vector<Type>{
597 #define X(y) T##y,
598 HHBBC_TYPE_SINGLE(X)
599 #undef X
603 std::vector<Type> withData(const Index& index) {
604 std::vector<Type> types;
606 auto const clsA = index.resolve_class(Context{}, s_A.get());
607 if (!clsA || !clsA->resolved()) ADD_FAILURE();
608 auto const clsAA = index.resolve_class(Context{}, s_AA.get());
609 if (!clsAA || !clsAA->resolved()) ADD_FAILURE();
610 auto const clsAB = index.resolve_class(Context{}, s_AB.get());
611 if (!clsAB || !clsAB->resolved()) ADD_FAILURE();
613 auto const clsIBase = index.resolve_class(Context{}, s_IBase.get());
614 if (!clsIBase || !clsIBase->resolved()) ADD_FAILURE();
615 auto const clsIA = index.resolve_class(Context{}, s_IA.get());
616 if (!clsIA || !clsIA->resolved()) ADD_FAILURE();
617 auto const clsIAA = index.resolve_class(Context{}, s_IAA.get());
618 if (!clsIAA || !clsIAA->resolved()) ADD_FAILURE();
619 auto const clsIB = index.resolve_class(Context{}, s_IB.get());
620 if (!clsIB || !clsIB->resolved()) ADD_FAILURE();
622 auto const clsI_A = index.resolve_class(Context{}, s_I_A.get());
623 if (!clsI_A || !clsI_A->resolved()) ADD_FAILURE();
624 auto const clsI_B = index.resolve_class(Context{}, s_I_B.get());
625 if (!clsI_B || !clsI_B->resolved()) ADD_FAILURE();
626 auto const clsI_C = index.resolve_class(Context{}, s_I_C.get());
627 if (!clsI_C || !clsI_C->resolved()) ADD_FAILURE();
628 auto const clsI_D = index.resolve_class(Context{}, s_I_D.get());
629 if (!clsI_D || !clsI_D->resolved()) ADD_FAILURE();
630 auto const clsI_E = index.resolve_class(Context{}, s_I_E.get());
631 if (!clsI_E || !clsI_E->resolved()) ADD_FAILURE();
632 auto const clsI_F = index.resolve_class(Context{}, s_I_F.get());
633 if (!clsI_F || !clsI_F->resolved()) ADD_FAILURE();
634 auto const clsI_G = index.resolve_class(Context{}, s_I_G.get());
635 if (!clsI_G || !clsI_G->resolved()) ADD_FAILURE();
636 auto const clsI_H = index.resolve_class(Context{}, s_I_H.get());
637 if (!clsI_H || !clsI_H->resolved()) ADD_FAILURE();
638 auto const clsI_I = index.resolve_class(Context{}, s_I_I.get());
639 if (!clsI_I || !clsI_I->resolved()) ADD_FAILURE();
640 auto const clsI_J = index.resolve_class(Context{}, s_I_J.get());
641 if (!clsI_J || !clsI_J->resolved()) ADD_FAILURE();
642 auto const clsI_K = index.resolve_class(Context{}, s_I_K.get());
643 if (!clsI_K || !clsI_K->resolved()) ADD_FAILURE();
645 auto const clsX1 = index.resolve_class(Context{}, s_X1.get());
646 if (!clsX1 || !clsX1->resolved()) ADD_FAILURE();
647 auto const clsX2 = index.resolve_class(Context{}, s_X2.get());
648 if (!clsX2 || !clsX2->resolved()) ADD_FAILURE();
649 auto const clsX3 = index.resolve_class(Context{}, s_X3.get());
650 if (!clsX3 || !clsX3->resolved()) ADD_FAILURE();
651 auto const clsX4 = index.resolve_class(Context{}, s_X4.get());
652 if (!clsX4 || !clsX4->resolved()) ADD_FAILURE();
653 auto const clsX7 = index.resolve_class(Context{}, s_X7.get());
654 if (!clsX7 || !clsX7->resolved()) ADD_FAILURE();
655 auto const clsX11 = index.resolve_class(Context{}, s_X11.get());
656 if (!clsX11 || !clsX11->resolved()) ADD_FAILURE();
657 auto const clsX21 = index.resolve_class(Context{}, s_X21.get());
658 if (!clsX21 || !clsX21->resolved()) ADD_FAILURE();
660 auto const clsFoo1 = index.resolve_class(Context{}, s_Foo1.get());
661 if (!clsFoo1 || clsFoo1->resolved()) ADD_FAILURE();
662 auto const clsFoo2 = index.resolve_class(Context{}, s_Foo2.get());
663 if (!clsFoo2 || clsFoo2->resolved()) ADD_FAILURE();
665 auto const svec1 = static_vec(s_A.get(), s_B.get());
666 auto const svec2 = static_vec(123, 456);
667 auto const sdict1 = static_dict(s_A.get(), s_B.get(), s_C.get(), 123);
668 auto const sdict2 = static_dict(100, s_A.get(), 200, s_C.get());
669 auto const skeyset1 = static_keyset(s_A.get(), s_B.get());
670 auto const skeyset2 = static_keyset(123, 456);
672 auto const support = BStr | BDbl | BInt | BCls | BObj |
673 BArrLikeN | BLazyCls;
674 auto const nonSupport = BCell & ~support;
676 auto const add = [&] (trep b) {
677 types.emplace_back(Type{b});
679 if (b == BTop) return;
681 if (couldBe(b, BStr) && subtypeOf(b, BStr | nonSupport)) {
682 types.emplace_back(make_specialized_string(b, s_A.get()));
683 types.emplace_back(make_specialized_string(b, s_B.get()));
685 if (couldBe(b, BLazyCls) && subtypeOf(b, BLazyCls | nonSupport)) {
686 types.emplace_back(make_specialized_lazycls(b, s_A.get()));
687 types.emplace_back(make_specialized_lazycls(b, s_B.get()));
689 if (couldBe(b, BInt) && subtypeOf(b, BInt | nonSupport)) {
690 types.emplace_back(make_specialized_int(b, 123));
691 types.emplace_back(make_specialized_int(b, 456));
693 if (couldBe(b, BDbl) && subtypeOf(b, BDbl | nonSupport)) {
694 types.emplace_back(make_specialized_double(b, 3.141));
695 types.emplace_back(make_specialized_double(b, 2.718));
697 if (couldBe(b, BObj) && subtypeOf(b, BObj | nonSupport)) {
698 types.emplace_back(make_specialized_wait_handle(b, TInt, index));
699 types.emplace_back(make_specialized_wait_handle(b, TStr, index));
700 types.emplace_back(make_specialized_wait_handle(b, TArrKey, index));
701 types.emplace_back(make_specialized_wait_handle(b, TBottom, index));
703 types.emplace_back(make_specialized_exact_object(b, *clsA));
704 types.emplace_back(make_specialized_exact_object(b, *clsAA));
705 types.emplace_back(make_specialized_exact_object(b, *clsAB));
707 types.emplace_back(make_specialized_exact_object(b, *clsIBase));
708 types.emplace_back(make_specialized_exact_object(b, *clsIA));
709 types.emplace_back(make_specialized_exact_object(b, *clsIAA));
710 types.emplace_back(make_specialized_exact_object(b, *clsIB));
712 types.emplace_back(make_specialized_sub_object(b, *clsA));
713 types.emplace_back(make_specialized_sub_object(b, *clsAA));
714 types.emplace_back(make_specialized_sub_object(b, *clsAB));
716 auto const subIBase = make_specialized_sub_object(b, *clsIBase);
717 auto const subIA = make_specialized_sub_object(b, *clsIA);
718 auto const subIAA = make_specialized_sub_object(b, *clsIAA);
719 auto const subIB = make_specialized_sub_object(b, *clsIB);
720 types.emplace_back(subIBase);
721 types.emplace_back(subIA);
722 types.emplace_back(subIAA);
723 types.emplace_back(subIB);
725 if (subtypeOf(b, BInitCell)) {
726 types.emplace_back(make_specialized_wait_handle(b, subIBase, index));
727 types.emplace_back(make_specialized_wait_handle(b, subIA, index));
728 types.emplace_back(make_specialized_wait_handle(b, subIAA, index));
729 types.emplace_back(make_specialized_wait_handle(b, subIB, index));
732 types.emplace_back(make_specialized_exact_object(b, *clsA, true));
733 types.emplace_back(make_specialized_exact_object(b, *clsAA, true));
734 types.emplace_back(make_specialized_exact_object(b, *clsAB, true));
736 types.emplace_back(make_specialized_sub_object(b, *clsA, true));
737 types.emplace_back(make_specialized_sub_object(b, *clsAA, true));
738 types.emplace_back(make_specialized_sub_object(b, *clsAB, true));
740 auto const dobj =
741 dobj_of(make_specialized_wait_handle(b, TArrKey, index));
742 if (!dobj.cls().resolved()) ADD_FAILURE();
743 types.emplace_back(make_specialized_sub_object(b, dobj.cls()));
744 types.emplace_back(make_specialized_exact_object(b, dobj.cls()));
746 types.emplace_back(make_specialized_sub_object(b, *clsI_A));
747 types.emplace_back(make_specialized_exact_object(b, *clsI_A));
748 types.emplace_back(make_specialized_sub_object(b, *clsI_B));
749 types.emplace_back(make_specialized_exact_object(b, *clsI_B));
750 types.emplace_back(make_specialized_sub_object(b, *clsI_C));
751 types.emplace_back(make_specialized_sub_object(b, *clsI_E));
752 types.emplace_back(make_specialized_sub_object(b, *clsI_F));
753 types.emplace_back(make_specialized_sub_object(b, *clsI_G));
754 types.emplace_back(make_specialized_sub_object(b, *clsI_H));
755 types.emplace_back(make_specialized_sub_object(b, *clsI_J));
756 types.emplace_back(make_specialized_sub_object(b, *clsI_K));
758 types.emplace_back(make_specialized_sub_object(b, *clsX1));
759 types.emplace_back(make_specialized_sub_object(b, *clsX2));
760 types.emplace_back(make_specialized_exact_object(b, *clsX2));
761 types.emplace_back(make_specialized_sub_object(b, *clsX3));
762 types.emplace_back(make_specialized_exact_object(b, *clsX3));
763 types.emplace_back(make_specialized_sub_object(b, *clsX4));
764 types.emplace_back(make_specialized_sub_object(b, *clsX7));
765 types.emplace_back(make_specialized_sub_object(b, *clsX11));
766 types.emplace_back(make_specialized_sub_object(b, *clsX21));
768 types.emplace_back(make_specialized_exact_object(b, *clsFoo1));
769 types.emplace_back(make_specialized_sub_object(b, *clsFoo1));
770 types.emplace_back(make_specialized_exact_object(b, *clsFoo2));
771 types.emplace_back(make_specialized_sub_object(b, *clsFoo2));
773 if (couldBe(b, BCls) && subtypeOf(b, BCls | nonSupport)) {
774 types.emplace_back(make_specialized_exact_class(b, *clsA));
775 types.emplace_back(make_specialized_exact_class(b, *clsAA));
776 types.emplace_back(make_specialized_exact_class(b, *clsAB));
778 types.emplace_back(make_specialized_sub_class(b, *clsA));
779 types.emplace_back(make_specialized_sub_class(b, *clsAA));
780 types.emplace_back(make_specialized_sub_class(b, *clsAB));
782 types.emplace_back(make_specialized_exact_class(b, *clsA, true));
783 types.emplace_back(make_specialized_exact_class(b, *clsAA, true));
784 types.emplace_back(make_specialized_exact_class(b, *clsAB, true));
786 types.emplace_back(make_specialized_sub_class(b, *clsA, true));
787 types.emplace_back(make_specialized_sub_class(b, *clsAA, true));
788 types.emplace_back(make_specialized_sub_class(b, *clsAB, true));
791 if (couldBe(b, BArrLikeN) && subtypeOf(b, BArrLikeN | nonSupport)) {
792 if (subtypeAmong(b, BKeysetN, BArrLikeN)) {
793 types.emplace_back(make_specialized_arrpacked(b, {ival(0), ival(1)}));
794 types.emplace_back(make_specialized_arrpackedn(b, TInt));
795 types.emplace_back(make_specialized_arrmapn(b, TInt, TInt));
796 types.emplace_back(make_specialized_arrmap(b, {map_elem(1, ival(1))}));
797 types.emplace_back(make_specialized_arrmap(b, {map_elem(s_A, sval(s_A))}));
799 if (subtypeAmong(b, BSArrLikeN, BArrLikeN)) {
800 types.emplace_back(make_specialized_arrmapn(b, TSStr, TSStr));
801 } else {
802 types.emplace_back(make_specialized_arrmapn(b, TStr, TStr));
804 } else if (couldBe(b, BKeysetN)) {
805 types.emplace_back(make_specialized_arrpacked(b, {TInt, TInt}));
806 types.emplace_back(make_specialized_arrpacked(b, {TInitPrim, TInitPrim}));
807 types.emplace_back(make_specialized_arrpackedn(b, TInt));
808 types.emplace_back(make_specialized_arrpackedn(b, TInitPrim));
810 if (subtypeAmong(b, BSArrLikeN, BArrLikeN)) {
811 types.emplace_back(make_specialized_arrpacked(b, {TInitUnc, TInitUnc}));
812 types.emplace_back(make_specialized_arrpackedn(b, TUncArrKey));
813 types.emplace_back(make_specialized_arrmapn(b, TInt, TUncArrKey));
814 types.emplace_back(make_specialized_arrmapn(b, TUncArrKey, TSStr));
815 types.emplace_back(make_specialized_arrmapn(b, TUncArrKey, TUncArrKey));
816 } else {
817 types.emplace_back(make_specialized_arrpacked(b, {TInitCell, TInitCell}));
818 types.emplace_back(make_specialized_arrpackedn(b, TArrKey));
819 types.emplace_back(make_specialized_arrpackedn(b, union_of(TObj, TInt)));
820 types.emplace_back(make_specialized_arrmapn(b, TInt, TArrKey));
821 types.emplace_back(make_specialized_arrmapn(b, TArrKey, TStr));
822 types.emplace_back(make_specialized_arrmapn(b, TArrKey, TArrKey));
825 if (!couldBe(b, BVecN)) {
826 types.emplace_back(make_specialized_arrmap(b, {map_elem(1, TInt)}));
827 if (subtypeAmong(b, BSArrLikeN, BArrLikeN)) {
828 types.emplace_back(make_specialized_arrmap(b, {map_elem(s_A, TSStr)}));
829 types.emplace_back(make_specialized_arrmap(b, {map_elem(s_A, TInitUnc)}));
830 types.emplace_back(make_specialized_arrmap(b, {map_elem(s_A, TInitUnc)}, TInt, TSStr));
831 types.emplace_back(make_specialized_arrmap(b, {map_elem(s_A, TInitUnc)}, TSStr, TInt));
832 } else {
833 types.emplace_back(make_specialized_arrmap(b, {map_elem(s_A, TStr)}));
834 types.emplace_back(make_specialized_arrmap(b, {map_elem(s_A, TInitCell)}));
835 types.emplace_back(make_specialized_arrmap(b, {map_elem(s_A, TInitUnc)}, TInt, TStr));
836 types.emplace_back(make_specialized_arrmap(b, {map_elem(s_A, TInitUnc)}, TStr, TInt));
837 types.emplace_back(make_specialized_arrmap(b, {map_elem(s_A, TInitUnc)}, TStr, TObj));
840 } else {
841 types.emplace_back(make_specialized_arrpacked(b, {TInt, TInt}));
842 types.emplace_back(make_specialized_arrpackedn(b, TInt));
844 if (subtypeAmong(b, BSArrLikeN, BArrLikeN)) {
845 types.emplace_back(make_specialized_arrpacked(b, {TSStr, TSStr}));
846 types.emplace_back(make_specialized_arrpacked(b, {TInitUnc, TInitUnc}));
847 types.emplace_back(make_specialized_arrpackedn(b, TSStr));
848 types.emplace_back(make_specialized_arrpackedn(b, TUncArrKey));
849 } else {
850 types.emplace_back(make_specialized_arrpacked(b, {TStr, TStr}));
851 types.emplace_back(make_specialized_arrpacked(b, {TInitCell, TInitCell}));
852 types.emplace_back(make_specialized_arrpackedn(b, TStr));
853 types.emplace_back(make_specialized_arrpackedn(b, TArrKey));
854 types.emplace_back(make_specialized_arrpackedn(b, TObj));
857 if (!subtypeAmong(b, BVecN, BArrLikeN)) {
858 types.emplace_back(make_specialized_arrmapn(b, TInt, TInt));
859 if (subtypeAmong(b, BSArrLikeN, BArrLikeN)) {
860 if (!couldBe(b, BVecN)) {
861 types.emplace_back(make_specialized_arrmapn(b, TSStr, TSStr));
863 types.emplace_back(make_specialized_arrmapn(b, TUncArrKey, TUncArrKey));
864 } else {
865 if (!couldBe(b, BVecN)) {
866 types.emplace_back(make_specialized_arrmapn(b, TStr, TStr));
868 types.emplace_back(make_specialized_arrmapn(b, TArrKey, TArrKey));
869 types.emplace_back(make_specialized_arrmapn(b, TArrKey, TObj));
873 if (!couldBe(b, BVecN)) {
874 if (subtypeAmong(b, BSArrLikeN, BArrLikeN)) {
875 types.emplace_back(make_specialized_arrmap(b, {map_elem(1, TSStr)}));
876 types.emplace_back(make_specialized_arrmap(b, {map_elem(s_A, TInitUnc)}));
877 types.emplace_back(make_specialized_arrmap(b, {map_elem(s_A, TInitUnc)}, TInt, TSStr));
878 types.emplace_back(make_specialized_arrmap(b, {map_elem(s_A, TInitUnc)}, TSStr, TInt));
879 } else {
880 types.emplace_back(make_specialized_arrmap(b, {map_elem(1, TStr)}));
881 types.emplace_back(make_specialized_arrmap(b, {map_elem(s_A, TInitCell)}));
882 types.emplace_back(make_specialized_arrmap(b, {map_elem(s_A, TObj)}));
883 types.emplace_back(make_specialized_arrmap(b, {map_elem(s_A, TInitUnc)}, TInt, TStr));
884 types.emplace_back(make_specialized_arrmap(b, {map_elem(s_A, TInitUnc)}, TStr, TInt));
885 types.emplace_back(make_specialized_arrmap(b, {map_elem(s_A, TInitUnc)}, TStr, TObj));
887 types.emplace_back(make_specialized_arrmap(b, {map_elem(s_A, TInt)}));
891 if (subtypeAmong(b, BSVecN, BArrLikeN)) {
892 types.emplace_back(make_specialized_arrval(b, svec1));
893 types.emplace_back(make_specialized_arrval(b, svec2));
895 if (subtypeAmong(b, BSDictN, BArrLikeN)) {
896 types.emplace_back(make_specialized_arrval(b, sdict1));
897 types.emplace_back(make_specialized_arrval(b, sdict2));
899 if (subtypeAmong(b, BSKeysetN, BArrLikeN)) {
900 types.emplace_back(make_specialized_arrval(b, skeyset1));
901 types.emplace_back(make_specialized_arrval(b, skeyset2));
906 for (auto const& t : predefined()) add(t.first);
908 make_unmarked(types);
909 return types;
912 auto const specialized_arrays = folly::lazy([]{
913 std::vector<Type> types;
915 auto const add = [&] (trep b) {
916 if (!b) return;
918 types.emplace_back(Type{b});
920 auto const containsUncounted = [] (trep bits) {
921 if ((bits & BVecN) == BSVecN) return true;
922 if ((bits & BDictN) == BSDictN) return true;
923 if ((bits & BKeysetN) == BSKeysetN) return true;
924 return false;
927 auto const keyBits = [&containsUncounted] (trep bits) {
928 auto upper = BBottom;
929 auto lower = BArrKey;
931 if (couldBe(bits, BVec)) {
932 upper |= BInt;
933 lower &= BInt;
934 bits &= ~BVec;
936 if (couldBe(bits, BArrLikeN)) {
937 if (subtypeOf(bits, BSArrLikeN)) {
938 upper |= BUncArrKey;
939 lower &= BUncArrKey;
940 } else {
941 upper |= BArrKey;
942 lower &= containsUncounted(bits) ? BUncArrKey : BArrKey;
945 return std::make_pair(upper, lower);
946 }(b);
948 auto const calcValBits = [&containsUncounted] (trep bits, bool packed) {
949 auto upper = BBottom;
950 auto lower = BInitCell;
952 if (couldBe(bits, BKeysetN)) {
953 if (packed) {
954 upper |= BInt;
955 lower &= BInt;
956 } else if (subtypeAmong(bits, BSKeysetN, BKeysetN)) {
957 upper |= BUncArrKey;
958 lower |= BUncArrKey;
959 } else {
960 upper |= BArrKey;
961 lower &= BArrKey;
963 bits &= ~BKeysetN;
965 if (couldBe(bits, BArrLikeN)) {
966 if (subtypeOf(bits, BSArrLikeN)) {
967 upper |= BInitUnc;
968 lower &= BInitUnc;
969 } else {
970 upper |= BInitCell;
971 lower &= containsUncounted(bits) ? BInitUnc : BInitCell;
974 return std::make_pair(upper, lower);
976 auto const packedValBits = calcValBits(b, true);
977 auto const valBits = calcValBits(b, false);
979 auto const packedn = [&] (const Type& t) {
980 if (!t.subtypeOf(packedValBits.first)) return;
981 if (!t.couldBe(packedValBits.second)) return;
982 if (subtypeOf(b, BVecN) && !t.strictSubtypeOf(packedValBits.first)) {
983 return;
985 types.emplace_back(make_specialized_arrpackedn(b, t));
987 packedn(TInt);
988 packedn(TSStr);
989 packedn(TStr);
990 packedn(TUncArrKey);
991 packedn(TArrKey);
992 packedn(TObj);
993 packedn(TInitUnc);
994 packedn(TInitCell);
995 packedn(Type{BInt|BObj});
996 packedn(Type{BInitCell & ~BObj});
997 packedn(Type{BInitUnc & ~BSStr});
999 auto const packed = [&] (const std::vector<Type>& elems) {
1000 for (size_t i = 0; i < elems.size(); ++i) {
1001 auto const& t = elems[i];
1002 if (!t.subtypeOf(packedValBits.first)) return;
1003 if (!t.couldBe(packedValBits.second)) return;
1004 if (couldBe(b, BKeysetN) && !t.couldBe(ival(i))) return;
1005 if (subtypeOf(b, BKeysetN) && !t.subtypeOf(ival(i))) return;
1007 types.emplace_back(make_specialized_arrpacked(b, elems));
1009 packed({TInt, TInt});
1010 packed({TSStr, TSStr});
1011 packed({TStr, TStr});
1012 packed({TUncArrKey, TUncArrKey});
1013 packed({TArrKey, TArrKey});
1014 packed({TObj, TObj});
1015 packed({TInitUnc, TInitUnc});
1016 packed({TInitCell, TInitCell});
1017 packed({Type{BInt|BObj}, Type{BInt|BObj}});
1018 packed({TInt, TObj});
1019 packed({TSStr, TStr});
1020 packed({ival(0)});
1021 packed({ival(0), ival(1)});
1022 packed({ival(100), ival(200)});
1023 packed({union_of(TObj,ival(0)), union_of(TObj,ival(1))});
1024 packed({TInt, TInt, TInt});
1025 packed({TObj, TObj, TObj});
1026 packed({TArrKey, TArrKey, TArrKey});
1028 auto const mapn = [&] (const Type& key, const Type& val) {
1029 if (subtypeOf(b, BVecN)) return;
1030 if (!key.subtypeOf(keyBits.first)) return;
1031 if (!key.couldBe(keyBits.second)) return;
1032 if (!val.subtypeOf(valBits.first)) return;
1033 if (!val.couldBe(valBits.second)) return;
1034 if (!key.strictSubtypeOf(keyBits.first) &&
1035 !val.strictSubtypeOf(valBits.first)) return;
1036 if (couldBe(b, BKeysetN) && !key.couldBe(val)) return;
1037 if (subtypeOf(b, BKeysetN) && key != val) return;
1038 types.emplace_back(make_specialized_arrmapn(b, key, val));
1040 mapn(TInt, TInt);
1041 mapn(TSStr, TSStr);
1042 mapn(TStr, TStr);
1043 mapn(TUncArrKey, TUncArrKey);
1044 mapn(TArrKey, TArrKey);
1045 mapn(TUncArrKey, TInt);
1046 mapn(TUncArrKey, TSStr);
1047 mapn(TInt, TUncArrKey);
1048 mapn(TSStr, TUncArrKey);
1049 mapn(TInt, TSStr);
1050 mapn(TSStr, TInt);
1051 mapn(TUncArrKey, TObj);
1052 mapn(TArrKey, TObj);
1053 mapn(TUncArrKey, TInitUnc);
1054 mapn(TArrKey, TInitUnc);
1055 mapn(TUncArrKey, TInitCell);
1056 mapn(TArrKey, TInitCell);
1057 mapn(TInt, Type{BInt|BObj});
1058 mapn(TSStr, Type{BInt|BObj});
1059 mapn(TInt, TInitUnc);
1060 mapn(TSStr, TInitUnc);
1061 mapn(TArrKey, Type{BInitCell & ~BObj});
1062 mapn(TUncArrKey, Type{BInitUnc & ~BSStr});
1063 mapn(TInt, TInitCell);
1064 mapn(TStr, TInitCell);
1066 auto const map = [&] (const MapElems& elems,
1067 const Type& optKey = TBottom,
1068 const Type& optVal = TBottom) {
1069 if (couldBe(b, BVecN)) return;
1071 for (auto const& e : elems) {
1072 if (!e.second.val.subtypeOf(valBits.first)) return;
1073 if (!e.second.val.couldBe(valBits.second)) return;
1075 auto const key = [&] {
1076 if (isIntType(e.first.m_type)) return ival(e.first.m_data.num);
1077 switch (e.second.keyStaticness) {
1078 case TriBool::Yes: return HPHP::HHBBC::sval(e.first.m_data.pstr);
1079 case TriBool::Maybe: return HPHP::HHBBC::sval_nonstatic(e.first.m_data.pstr);
1080 case TriBool::No: return HPHP::HHBBC::sval_counted(e.first.m_data.pstr);
1082 always_assert(false);
1083 }();
1085 if (!key.subtypeOf(keyBits.first)) return;
1086 if (!key.couldBe(keyBits.second)) return;
1088 if (couldBe(b, BKeysetN) && !key.couldBe(e.second.val)) return;
1089 if (subtypeOf(b, BKeysetN) && key != e.second.val) return;
1091 if (!optKey.is(BBottom)) {
1092 if (!optKey.subtypeOf(keyBits.first)) return;
1093 if (!optVal.subtypeOf(valBits.first)) return;
1094 if (subtypeOf(b, BKeysetN) && optKey != optVal) return;
1096 types.emplace_back(make_specialized_arrmap(b, elems, optKey, optVal));
1098 map({map_elem(s_A, TInt)});
1099 map({map_elem(s_A, TSStr)});
1100 map({map_elem(s_A, TStr)});
1101 map({map_elem(s_A, sval(s_A))});
1102 map({map_elem(s_A, sval_nonstatic(s_A))});
1103 map({map_elem(s_A, TUncArrKey)});
1104 map({map_elem(s_A, TArrKey)});
1105 map({map_elem(s_A, TObj)});
1106 map({map_elem(s_A, TInitUnc)});
1107 map({map_elem(s_A, TInitCell)});
1108 map({map_elem(s_A, Type{BInt|BObj})});
1109 map({map_elem(s_A, TInt)}, TInt, TInt);
1110 map({map_elem(s_A, TInt)}, TInt, TSStr);
1111 map({map_elem(s_A, TInt)}, TInt, TStr);
1112 map({map_elem(s_A, TInt)}, TInt, TUncArrKey);
1113 map({map_elem(s_A, TInt)}, TInt, TArrKey);
1114 map({map_elem(s_A, TInt)}, TInt, TObj);
1115 map({map_elem(s_A, TInt)}, TInt, TInitUnc);
1116 map({map_elem(s_A, TInt)}, TInt, TInitCell);
1117 map({map_elem(s_A, TInt)}, TSStr, TInt);
1118 map({map_elem(s_A, TInt)}, TSStr, TSStr);
1119 map({map_elem(s_A, TInt)}, TSStr, TStr);
1120 map({map_elem(s_A, TInt)}, TSStr, TUncArrKey);
1121 map({map_elem(s_A, TInt)}, TSStr, TArrKey);
1122 map({map_elem(s_A, TInt)}, TSStr, TObj);
1123 map({map_elem(s_A, TInt)}, TSStr, TInitUnc);
1124 map({map_elem(s_A, TInt)}, TSStr, TInitCell);
1125 map({map_elem(s_A, sval(s_A))}, TInt, Type{BInt|BObj});
1126 map({map_elem(s_B, TInt)});
1127 map({map_elem(s_B, sval(s_B))});
1128 map({map_elem(123, TInt)});
1129 map({map_elem(123, TSStr)});
1130 map({map_elem(123, TStr)});
1131 map({map_elem(123, ival(123))});
1132 map({map_elem(123, TUncArrKey)});
1133 map({map_elem(123, TArrKey)});
1134 map({map_elem(123, TObj)});
1135 map({map_elem(123, TInitUnc)});
1136 map({map_elem(123, TInitCell)});
1137 map({map_elem(123, Type{BInt|BObj})});
1138 map({map_elem(std::numeric_limits<int64_t>::max(), TStr)});
1139 map({map_elem_nonstatic(s_A, TInt)});
1140 map({map_elem_nonstatic(s_A, TSStr)});
1141 map({map_elem_nonstatic(s_A, TStr)});
1142 map({map_elem_nonstatic(s_A, sval(s_A))});
1143 map({map_elem_nonstatic(s_A, sval_nonstatic(s_A))});
1144 map({map_elem_nonstatic(s_A, Type{BStr|BObj})});
1147 auto const bits = std::vector<trep>{
1148 BCVecN,
1149 BSVecN,
1150 BCDictN,
1151 BSDictN,
1152 BCKeysetN,
1153 BSKeysetN,
1156 auto const subsetSize = 1ULL << bits.size();
1157 for (size_t i = 0; i < subsetSize; ++i) {
1158 auto b = BBottom;
1159 for (size_t j = 0; j < bits.size(); ++j) {
1160 if (i & (1ULL << j)) b |= bits[j];
1162 add(b);
1165 auto const svec1 = static_vec(s_A.get(), s_B.get());
1166 auto const svec2 = static_vec(123, 456);
1167 auto const sdict1 = static_dict(s_A.get(), s_B.get(), s_C.get(), 123);
1168 auto const sdict2 = static_dict(100, s_A.get(), 200, s_C.get());
1169 auto const skeyset1 = static_keyset(s_A.get(), s_B.get());
1170 auto const skeyset2 = static_keyset(123, 456);
1172 types.emplace_back(make_specialized_arrval(BSVecN, svec1));
1173 types.emplace_back(make_specialized_arrval(BSVecN, svec2));
1174 types.emplace_back(make_specialized_arrval(BSDictN, sdict1));
1175 types.emplace_back(make_specialized_arrval(BSDictN, sdict2));
1176 types.emplace_back(make_specialized_arrval(BSKeysetN, skeyset1));
1177 types.emplace_back(make_specialized_arrval(BSKeysetN, skeyset2));
1179 types.emplace_back(make_specialized_arrpackedn(BVecN|BKeysetN, ival(0)));
1181 make_unmarked(types);
1182 return types;
1185 std::vector<Type> allCases(const Index& index) {
1186 auto types = withData(index);
1187 auto const specialized = specialized_arrays();
1188 types.insert(types.end(), specialized.begin(), specialized.end());
1189 return types;
1192 auto const allBits = folly::lazy([]{
1193 std::vector<trep> bits;
1195 for (auto const& p : predefined()) {
1196 bits.emplace_back(p.first);
1197 if (!(p.first & BInitNull)) bits.emplace_back(p.first | BInitNull);
1200 auto const arrbits = std::vector<trep>{
1201 BCVecN,
1202 BSVecN,
1203 BCDictN,
1204 BSDictN,
1205 BCKeysetN,
1206 BSKeysetN,
1209 auto const subsetSize = 1ULL << arrbits.size();
1210 for (size_t i = 0; i < subsetSize; ++i) {
1211 auto b = BBottom;
1212 for (size_t j = 0; j < arrbits.size(); ++j) {
1213 if (i & (1ULL << j)) b |= arrbits[j];
1215 bits.emplace_back(b);
1216 bits.emplace_back(b | BInitNull);
1219 bits.emplace_back(BObj | BInt);
1220 bits.emplace_back(BObj | BInt | BInitNull);
1222 return bits;
1225 //////////////////////////////////////////////////////////////////////
1229 TEST(Type, Bits) {
1230 auto const program = make_test_program();
1231 Index index { program.get() };
1233 for (auto const& t : predefined()) {
1234 EXPECT_EQ(Type{t.first}, t.second);
1235 EXPECT_TRUE(t.second.is(t.first));
1236 EXPECT_TRUE(t.second.subtypeOf(t.first));
1237 EXPECT_FALSE(t.second.strictSubtypeOf(t.first));
1238 if (t.first != BBottom) {
1239 EXPECT_TRUE(t.second.couldBe(t.first));
1243 for (auto const& t : allCases(index)) {
1244 for (auto const b : allBits()) {
1245 EXPECT_EQ(t.subtypeOf(b), t.subtypeOf(Type{b}));
1246 EXPECT_EQ(loosen_mark_for_testing(t).strictSubtypeOf(b),
1247 loosen_mark_for_testing(t).strictSubtypeOf(Type{b}));
1248 if (!is_specialized_array_like(t)) {
1249 EXPECT_EQ(t.couldBe(b), t.couldBe(Type{b}));
1250 } else if (!t.couldBe(b)) {
1251 EXPECT_FALSE(t.couldBe(Type{b}));
1257 TEST(Type, Top) {
1258 auto const program = make_test_program();
1259 Index index { program.get() };
1261 // Everything is a subtype of Top, couldBe Top, and the union of Top
1262 // with anything is Top.
1263 for (auto const& t : allCases(index)) {
1264 if (!t.is(BTop)) {
1265 EXPECT_FALSE(TTop.subtypeOf(t));
1267 EXPECT_FALSE(TTop.strictSubtypeOf(t));
1268 EXPECT_TRUE(t.subtypeOf(BTop));
1269 if (!t.is(BBottom)) {
1270 EXPECT_TRUE(TTop.couldBe(t));
1271 EXPECT_TRUE(t.couldBe(BTop));
1273 EXPECT_EQ(union_of(t, TTop), TTop);
1274 EXPECT_EQ(union_of(TTop, t), TTop);
1275 EXPECT_EQ(intersection_of(TTop, t), t);
1276 EXPECT_EQ(intersection_of(t, TTop), t);
1280 TEST(Type, Bottom) {
1281 auto const program = make_test_program();
1282 Index index { program.get() };
1284 // Bottom is a subtype of everything, nothing couldBe Bottom, and
1285 // the union_of anything with Bottom is itself.
1286 for (auto const& t : allCases(index)) {
1287 EXPECT_TRUE(TBottom.subtypeOf(t));
1288 EXPECT_FALSE(TBottom.couldBe(t));
1289 if (!t.is(BBottom)) {
1290 EXPECT_FALSE(t.subtypeOf(BBottom));
1292 EXPECT_FALSE(t.strictSubtypeOf(BBottom));
1293 EXPECT_FALSE(t.couldBe(BBottom));
1294 EXPECT_EQ(union_of(t, TBottom), t);
1295 EXPECT_EQ(union_of(TBottom, t), t);
1296 EXPECT_EQ(intersection_of(TBottom, t), TBottom);
1297 EXPECT_EQ(intersection_of(t, TBottom), TBottom);
1301 TEST(Type, Prims) {
1302 auto const program = make_test_program();
1303 Index index { program.get() };
1305 // All pairs of non-equivalent primitives are not related by either
1306 // subtypeOf or couldBe, except for wait-handles, which always could
1307 // be each other.
1308 for (auto const& t1 : primitives()) {
1309 for (auto const& t2 : primitives()) {
1310 if (t1 == t2) continue;
1312 auto const test = [] (const Type& a, const Type& b, bool isWaitHandle) {
1313 EXPECT_TRUE(!a.subtypeOf(b));
1314 EXPECT_TRUE(!a.strictSubtypeOf(b));
1315 EXPECT_TRUE(!b.subtypeOf(a));
1316 EXPECT_TRUE(!b.strictSubtypeOf(a));
1317 if (!isWaitHandle) {
1318 EXPECT_TRUE(!a.couldBe(b));
1319 EXPECT_TRUE(!b.couldBe(a));
1320 EXPECT_EQ(intersection_of(a, b), TBottom);
1321 } else {
1322 EXPECT_TRUE(a.couldBe(b));
1323 EXPECT_TRUE(b.couldBe(a));
1324 EXPECT_NE(intersection_of(a, b), TBottom);
1328 test(t1, t2, false);
1330 if (t1.is(BUninit) || t2.is(BUninit)) continue;
1332 test(wait_handle(index, t1), wait_handle(index, t2), true);
1334 const std::vector<Type> arrays1{
1335 dict_packed({t1, t1}),
1336 dict_packedn(t1),
1337 dict_map({map_elem(5, t1)}),
1338 dict_n(TInt, t1)
1340 const std::vector<Type> arrays2{
1341 dict_packed({t2, t2}),
1342 dict_packedn(t2),
1343 dict_map({map_elem(5, t2)}),
1344 dict_n(TInt, t2)
1346 for (auto const& a1 : arrays1) {
1347 for (auto const& a2 : arrays2) test(a1, a2, false);
1353 namespace {
1355 void test_basic_operators(const std::vector<Type>& types) {
1356 for (auto const& t : types) {
1357 EXPECT_EQ(t, t);
1358 EXPECT_TRUE(t.equivalentlyRefined(t));
1359 EXPECT_TRUE(t.subtypeOf(t));
1360 EXPECT_TRUE(t.moreRefined(t));
1361 EXPECT_FALSE(t.strictSubtypeOf(t));
1362 EXPECT_FALSE(t.strictlyMoreRefined(t));
1363 if (!t.is(BBottom)) {
1364 EXPECT_TRUE(t.couldBe(t));
1366 EXPECT_EQ(union_of(t, t), t);
1367 EXPECT_EQ(intersection_of(t, t), t);
1368 if (!t.is(BBottom)) {
1369 EXPECT_TRUE(opt(t).couldBe(t));
1371 EXPECT_TRUE(t.subtypeOf(opt(t)));
1372 EXPECT_EQ(opt(t), union_of(t, TInitNull));
1373 if (t.subtypeOf(BCell)) {
1374 EXPECT_EQ(unopt(t), remove_bits(t, BInitNull));
1375 EXPECT_FALSE(unopt(t).couldBe(BInitNull));
1377 if (!t.couldBe(BInitNull)) {
1378 EXPECT_EQ(t, unopt(opt(t)));
1382 auto const isCtxful = [] (const Type& t1, const Type& t2) {
1383 if (is_specialized_obj(t1) && is_specialized_obj(t2)) {
1384 if (is_specialized_wait_handle(t1) || is_specialized_wait_handle(t2)) {
1385 return false;
1387 return dobj_of(t1).isCtx() != dobj_of(t2).isCtx();
1389 if (!is_specialized_cls(t1) || !is_specialized_cls(t2)) return false;
1390 return dcls_of(t1).isCtx() != dcls_of(t2).isCtx();
1393 auto const matchingData = [] (const Type& t1, const Type& t2, auto const& self) {
1394 if (!t1.hasData()) return true;
1395 if (is_specialized_array_like(t1)) {
1396 return is_specialized_array_like(t2) || !t2.hasData();
1398 if (is_specialized_string(t1)) {
1399 return is_specialized_string(t2) || !t2.hasData();
1401 if (is_specialized_int(t1)) {
1402 return is_specialized_int(t2) || !t2.hasData();
1404 if (is_specialized_double(t1)) {
1405 return is_specialized_double(t2) || !t2.hasData();
1407 if (is_specialized_cls(t1)) {
1408 return is_specialized_cls(t2) || !t2.hasData();
1410 if (is_specialized_wait_handle(t1) && is_specialized_wait_handle(t2)) {
1411 return self(wait_handle_inner(t1), wait_handle_inner(t2), self);
1413 if (is_specialized_obj(t1)) {
1414 if (!t2.hasData()) return true;
1415 return is_specialized_obj(t2);
1417 return true;
1420 for (size_t i1 = 0; i1 < types.size(); ++i1) {
1421 for (size_t i2 = 0; i2 < types.size(); ++i2) {
1422 auto const& t1 = types[i1];
1423 auto const& t2 = types[i2];
1425 auto const ctxful = isCtxful(t1, t2);
1427 auto const equivRefined = t1.equivalentlyRefined(t2);
1428 auto const moreRefined = t1.moreRefined(t2);
1429 auto const couldBe = t1.couldBe(t2);
1431 if (t1.strictlyMoreRefined(t2)) {
1432 EXPECT_FALSE(equivRefined);
1433 EXPECT_TRUE(moreRefined);
1435 if (t1.strictSubtypeOf(t2)) {
1436 EXPECT_NE(t1, t2);
1437 EXPECT_TRUE(t1.subtypeOf(t2));
1440 if (equivRefined) {
1441 EXPECT_TRUE(t1 == t2);
1443 if (moreRefined) {
1444 EXPECT_TRUE(t1.subtypeOf(t2));
1446 if (t1.strictlyMoreRefined(t2)) {
1447 EXPECT_TRUE(t1.strictSubtypeOf(t2) || t1 == t2);
1450 if (!ctxful) {
1451 EXPECT_EQ(t1 == t2, equivRefined);
1452 EXPECT_EQ(t1.subtypeOf(t2), moreRefined);
1453 EXPECT_EQ(t1.strictSubtypeOf(t2), t1.strictlyMoreRefined(t2));
1456 if (i1 == i2) {
1457 EXPECT_TRUE(equivRefined);
1458 EXPECT_FALSE(t1.strictlyMoreRefined(t2));
1459 EXPECT_FALSE(t1.strictSubtypeOf(t2));
1462 auto const uni = union_of(t1, t2);
1463 auto const isect = intersection_of(t1, t2);
1465 EXPECT_EQ(t1 == t2, t2 == t1);
1466 EXPECT_EQ(equivRefined, t2.equivalentlyRefined(t1));
1467 EXPECT_EQ(couldBe, t2.couldBe(t1));
1468 EXPECT_EQ(uni, union_of(t2, t1));
1469 EXPECT_EQ(isect, intersection_of(t2, t1));
1471 EXPECT_TRUE(t1.moreRefined(uni));
1472 if (matchingData(t1, t2, matchingData)) {
1473 EXPECT_TRUE(isect.moreRefined(t1));
1474 EXPECT_TRUE(intersection_of(uni, t1).equivalentlyRefined(t1));
1475 } else {
1476 EXPECT_TRUE(isect.moreRefined(t1) || isect.moreRefined(t2));
1477 EXPECT_TRUE(intersection_of(uni, t1).equivalentlyRefined(t1) ||
1478 intersection_of(uni, t2).equivalentlyRefined(t2));
1481 if (moreRefined) {
1482 EXPECT_TRUE(uni.equivalentlyRefined(t2));
1483 EXPECT_TRUE(isect.equivalentlyRefined(t1));
1486 if (couldBe) {
1487 if (!is_specialized_array_like(t1) && !is_specialized_array_like(t2)) {
1488 EXPECT_FALSE(isect.is(BBottom));
1490 } else {
1491 EXPECT_TRUE(isect.is(BBottom));
1494 if (!t1.is(BBottom)) {
1495 if (moreRefined) {
1496 EXPECT_TRUE(couldBe);
1498 if (!couldBe) {
1499 EXPECT_FALSE(moreRefined);
1501 EXPECT_TRUE(t1.couldBe(uni));
1504 if (!isect.is(BBottom)) {
1505 EXPECT_TRUE(isect.couldBe(t1));
1510 for (auto const& t : types) {
1511 if (t.couldBe(BVec)) {
1512 EXPECT_FALSE(intersection_of(t, TVec).is(BBottom));
1514 if (t.couldBe(BDict)) {
1515 EXPECT_FALSE(intersection_of(t, TDict).is(BBottom));
1517 if (t.couldBe(BKeyset)) {
1518 EXPECT_FALSE(intersection_of(t, TKeyset).is(BBottom));
1525 TEST(Type, BasicOperators) {
1526 auto const program = make_test_program();
1527 Index index { program.get() };
1528 test_basic_operators(withData(index));
1530 EXPECT_EQ(union_of(ival(0),TStr), TArrKey);
1531 EXPECT_EQ(union_of(TInt,sval(s_A)), TUncArrKey);
1534 TEST(Type, SpecializedClasses) {
1535 auto const program = make_test_program();
1536 Index index { program.get() };
1538 std::vector<Type> baseTypes;
1540 #define ADD(cls, name, addExact) \
1541 auto const cls = index.resolve_class(Context{}, name.get()); \
1542 if (!cls || !cls->resolved()) ADD_FAILURE(); \
1543 if (cls->couldBeOverriden()) { \
1544 baseTypes.emplace_back(make_specialized_sub_object(BObj, *cls)); \
1546 if (addExact) { \
1547 baseTypes.emplace_back(make_specialized_exact_object(BObj, *cls)); \
1550 ADD(clsI_A, s_I_A, true);
1551 ADD(clsI_B, s_I_B, true);
1552 ADD(clsI_C, s_I_C, true);
1553 ADD(clsI_D, s_I_D, false);
1554 ADD(clsI_E, s_I_E, false);
1555 ADD(clsI_F, s_I_F, false);
1556 ADD(clsI_G, s_I_G, false);
1557 ADD(clsI_H, s_I_H, false);
1558 ADD(clsI_I, s_I_I, false);
1559 ADD(clsI_J, s_I_J, false);
1560 ADD(clsI_K, s_I_K, false);
1562 ADD(clsX1, s_X1, true);
1563 ADD(clsX2, s_X2, true);
1564 ADD(clsX3, s_X3, true);
1565 ADD(clsX4, s_X4, true);
1566 ADD(clsX5, s_X5, true);
1567 ADD(clsX6, s_X6, true);
1568 ADD(clsX7, s_X7, true);
1569 ADD(clsX8, s_X8, true);
1570 ADD(clsX9, s_X9, true);
1571 ADD(clsX10, s_X10, true);
1572 ADD(clsX11, s_X11, true);
1573 ADD(clsX12, s_X12, true);
1574 ADD(clsX13, s_X13, true);
1575 ADD(clsX14, s_X14, true);
1576 ADD(clsX15, s_X15, true);
1577 ADD(clsX16, s_X16, true);
1578 ADD(clsX17, s_X17, true);
1579 ADD(clsX18, s_X18, true);
1580 ADD(clsX19, s_X19, true);
1581 ADD(clsX20, s_X20, true);
1582 ADD(clsX21, s_X21, true);
1583 ADD(clsX22, s_X22, true);
1584 ADD(clsX23, s_X23, true);
1585 ADD(clsX24, s_X24, true);
1586 ADD(clsX25, s_X25, true);
1587 ADD(clsX26, s_X26, true);
1588 ADD(clsX27, s_X27, true);
1589 ADD(clsX28, s_X28, true);
1590 ADD(clsX29, s_X29, true);
1592 ADD(clsBase, s_Base, true);
1593 ADD(clsA, s_A, true);
1594 ADD(clsAA, s_AA, true);
1595 ADD(clsAB, s_AB, true);
1596 ADD(clsB, s_B, true);
1597 ADD(clsBA, s_BA, true);
1598 ADD(clsBB, s_BB, true);
1599 ADD(clsBAA, s_BAA, true);
1600 ADD(clsIBase, s_IBase, true);
1601 ADD(clsIA, s_IA, true);
1602 ADD(clsIAA, s_IAA, true);
1603 ADD(clsIB, s_IB, true);
1605 ADD(clsY1, s_Y1, true);
1606 ADD(clsY2, s_Y2, true);
1607 ADD(clsY3, s_Y3, true);
1608 ADD(clsY4, s_Y4, true);
1609 ADD(clsY5, s_Y5, true);
1610 ADD(clsY6, s_Y6, true);
1611 ADD(clsY7, s_Y7, true);
1612 ADD(clsY8, s_Y8, true);
1613 ADD(clsY9, s_Y9, true);
1615 ADD(clsIY1, s_IY1, false);
1616 ADD(clsIY2, s_IY3, false);
1617 ADD(clsIY3, s_IY3, false);
1619 ADD(clsIZ1, s_IZ1, false);
1620 ADD(clsIZ2, s_IZ3, false);
1621 ADD(clsIZ3, s_IZ3, false);
1622 ADD(clsIZ4, s_IZ4, false);
1623 ADD(clsIZ5, s_IZ5, false);
1624 ADD(clsIZ6, s_IZ6, false);
1626 ADD(clsZ1, s_Z1, true);
1627 ADD(clsZ2, s_Z2, true);
1628 ADD(clsZ3, s_Z3, true);
1629 ADD(clsZ4, s_Z4, true);
1630 ADD(clsZ5, s_Z5, true);
1631 ADD(clsZ6, s_Z6, true);
1632 ADD(clsZ7, s_Z7, true);
1633 ADD(clsZ8, s_Z8, true);
1634 ADD(clsZ9, s_Z9, true);
1635 ADD(clsZ10, s_Z10, true);
1637 #undef ADD
1639 auto const clsFoo1 = index.resolve_class(Context{}, s_Foo1.get());
1640 if (!clsFoo1 || clsFoo1->resolved()) ADD_FAILURE();
1641 auto const clsFoo2 = index.resolve_class(Context{}, s_Foo2.get());
1642 if (!clsFoo2 || clsFoo2->resolved()) ADD_FAILURE();
1643 auto const clsC = index.resolve_class(Context{}, s_C.get());
1644 if (!clsC || clsC->resolved()) ADD_FAILURE();
1646 baseTypes.emplace_back(make_specialized_sub_object(BObj, *clsFoo1));
1647 baseTypes.emplace_back(make_specialized_exact_object(BObj, *clsFoo1));
1648 baseTypes.emplace_back(make_specialized_sub_object(BObj, *clsFoo2));
1649 baseTypes.emplace_back(make_specialized_exact_object(BObj, *clsFoo2));
1651 auto const awaitable = index.builtin_class(s_Awaitable.get());
1652 baseTypes.emplace_back(make_specialized_sub_object(BObj, awaitable));
1653 baseTypes.emplace_back(make_specialized_exact_object(BObj, awaitable));
1655 baseTypes.emplace_back(make_specialized_wait_handle(BObj, TInt, index));
1656 baseTypes.emplace_back(make_specialized_wait_handle(BObj, TStr, index));
1657 baseTypes.emplace_back(make_specialized_wait_handle(BObj, TArrKey, index));
1658 baseTypes.emplace_back(make_specialized_wait_handle(BObj, TBottom, index));
1660 baseTypes.emplace_back(TObj);
1662 auto const types = [&] {
1663 hphp_fast_set<Type, TypeHasher> precombinations{
1664 begin(baseTypes), end(baseTypes)
1666 while (true) {
1667 auto combinations = precombinations;
1668 auto const presize = combinations.size();
1669 for (auto const& a : precombinations) {
1670 for (auto const& b : precombinations) {
1671 combinations.emplace(union_of(a, b));
1672 combinations.emplace(intersection_of(a, b));
1675 if (presize == combinations.size()) break;
1676 precombinations = std::move(combinations);
1678 return std::vector<Type>{begin(precombinations), end(precombinations)};
1679 }();
1681 test_basic_operators(types);
1683 for (auto const& t1 : types) {
1684 for (auto const& t2 : types) {
1685 if (!t2.subtypeOf(t1)) continue;
1686 for (auto const& t3 : types) {
1687 auto const superU = union_of(t1, t3);
1688 auto const superI = intersection_of(t1, t3);
1689 for (auto const& t4 : types) {
1690 if (!t4.subtypeOf(t3)) continue;
1691 EXPECT_TRUE(union_of(t2, t4).subtypeOf(superU));
1692 EXPECT_TRUE(intersection_of(t2, t4).subtypeOf(superI));
1699 TEST(Type, SpecializedArrays) {
1700 test_basic_operators(specialized_arrays());
1702 EXPECT_EQ(
1703 intersection_of(
1704 make_specialized_arrmapn(BVecN|BKeysetN, TArrKey, TStr),
1705 make_specialized_arrmapn(BDictN|BKeysetN, TInt, TArrKey)
1707 TBottom
1709 EXPECT_EQ(
1710 intersection_of(
1711 make_specialized_arrmapn(BArrLikeN, TArrKey, TStr),
1712 make_specialized_arrmapn(BDictN|BKeysetN, TInt, TArrKey)
1714 make_specialized_arrmapn(BDictN, TInt, TStr)
1716 EXPECT_EQ(
1717 intersection_of(
1718 make_specialized_arrmapn(BVecN|BDictN, TArrKey, TInt),
1719 make_specialized_arrmapn(BVecN|BKeysetN, TArrKey, TInt)
1721 make_specialized_arrpackedn(BVecN, TInt)
1725 auto const map1 = make_specialized_arrmap(BDictN, {map_elem(s_A, ival(123))});
1726 auto const map2 = make_specialized_arrmap(BDictN, {map_elem_nonstatic(s_A, ival(123))});
1727 EXPECT_NE(map1, map2);
1728 EXPECT_TRUE(map1.couldBe(map2));
1729 EXPECT_TRUE(map2.couldBe(map1));
1730 EXPECT_TRUE(map1.subtypeOf(map2));
1731 EXPECT_FALSE(map2.subtypeOf(map1));
1732 EXPECT_EQ(union_of(map1, map2), map2);
1733 EXPECT_EQ(intersection_of(map1, map2), map1);
1736 EXPECT_EQ(
1737 intersection_of(
1738 make_specialized_arrpacked(BVecN, {TStr, TArrKey, Type{BInt|BObj}, TInitCell}),
1739 TSArrLikeN
1741 make_specialized_arrpacked(BSVecN, {TSStr, TUncArrKey, TInt, TInitUnc})
1743 EXPECT_EQ(
1744 intersection_of(
1745 make_specialized_arrpacked(BVecN, {TStr, TArrKey, TObj, TInitCell}),
1746 TSArrLikeN
1748 TBottom
1751 EXPECT_EQ(
1752 intersection_of(
1753 make_specialized_arrpacked(BVecN|BKeysetN, {TArrKey, TArrKey}),
1754 TKeysetN
1756 make_specialized_arrpacked(BKeysetN, {ival(0), ival(1)})
1759 EXPECT_EQ(
1760 intersection_of(
1761 make_specialized_arrpacked(BDictN|BVecN, {TObj}),
1762 Type{BSDictN|BVecN}
1764 make_specialized_arrpacked(BVecN, {TObj})
1767 EXPECT_EQ(
1768 intersection_of(
1769 make_specialized_arrpacked(BSDictN|BVecN, {TInitCell}),
1770 make_specialized_arrpacked(BCDictN|BSVecN, {TInitCell})
1772 make_specialized_arrpacked(BSVecN, {TInitUnc})
1775 EXPECT_EQ(
1776 intersection_of(
1777 make_specialized_arrpackedn(BVecN, TStr),
1778 TSArrLikeN
1780 make_specialized_arrpackedn(BSVecN, TSStr)
1782 EXPECT_EQ(
1783 intersection_of(
1784 make_specialized_arrpackedn(BVecN, TObj),
1785 TSArrLikeN
1787 TBottom
1790 EXPECT_EQ(
1791 intersection_of(
1792 make_specialized_arrpackedn(BVecN|BKeysetN, TArrKey),
1793 TKeysetN
1795 make_specialized_arrpackedn(BKeysetN, TInt)
1798 EXPECT_EQ(
1799 intersection_of(
1800 make_specialized_arrpackedn(BDictN|BVecN, TObj),
1801 Type{BSDictN|BVecN}
1803 make_specialized_arrpackedn(BVecN, TObj)
1806 EXPECT_EQ(
1807 intersection_of(
1808 make_specialized_arrpackedn(BDictN|BSVecN, Type{BInitCell & ~BObj}),
1809 make_specialized_arrpackedn(BSDictN|BCVecN, Type{BInitCell & ~BObj})
1811 make_specialized_arrpackedn(BSDictN, TInitUnc)
1814 EXPECT_EQ(
1815 intersection_of(
1816 make_specialized_arrmapn(BDictN|BVecN, TArrKey, TObj),
1817 TVecN
1819 make_specialized_arrpackedn(BVecN, TObj)
1822 EXPECT_EQ(
1823 intersection_of(
1824 make_specialized_arrmapn(BDictN, TArrKey, TStr),
1825 TSDictN
1827 make_specialized_arrmapn(BSDictN, TUncArrKey, TSStr)
1829 EXPECT_EQ(
1830 intersection_of(
1831 make_specialized_arrmapn(BDictN, TArrKey, TObj),
1832 TSDictN
1834 TBottom
1836 EXPECT_EQ(
1837 intersection_of(
1838 make_specialized_arrmapn(BDictN, TCStr, TStr),
1839 TSDictN
1841 TBottom
1844 EXPECT_EQ(
1845 intersection_of(
1846 make_specialized_arrmapn(BDictN|BKeysetN, TStr, TArrKey),
1847 make_specialized_arrmapn(BVecN|BKeysetN, TArrKey, TArrKey)
1849 make_specialized_arrmapn(BKeysetN, TStr, TStr)
1851 EXPECT_EQ(
1852 intersection_of(
1853 make_specialized_arrmapn(BDictN|BKeysetN, TStr, TArrKey),
1854 make_specialized_arrmapn(BVecN|BKeysetN, TArrKey, TInt)
1856 TBottom
1859 EXPECT_EQ(
1860 intersection_of(
1861 make_specialized_arrmapn(BDictN|BKeysetN, TStr, TArrKey),
1862 make_specialized_arrmapn(BDictN|BKeysetN, TArrKey, TInt)
1864 make_specialized_arrmapn(BDictN, TStr, TInt)
1867 EXPECT_EQ(
1868 intersection_of(
1869 make_specialized_arrmapn(BDictN|BCKeysetN, TCStr, TCStr),
1870 Type{BDictN|BSKeysetN}
1872 make_specialized_arrmapn(BDictN, TCStr, TCStr)
1875 EXPECT_EQ(
1876 intersection_of(
1877 make_specialized_arrmapn(BDictN|BKeysetN, TArrKey, Type{BInitCell & ~BObj}),
1878 make_specialized_arrmapn(BSDictN|BVecN, TUncArrKey, Type{BInitCell & ~BObj})
1880 TSDictN
1882 EXPECT_EQ(
1883 intersection_of(
1884 make_specialized_arrmapn(BCDictN|BSVecN, TArrKey, Type{BInitCell & ~BObj}),
1885 make_specialized_arrmapn(BSDictN|BVecN, TUncArrKey, Type{BInitCell & ~BObj})
1887 TSVecN
1890 EXPECT_EQ(
1891 intersection_of(
1892 make_specialized_arrmap(BDictN, {map_elem(s_A, TStr)}),
1893 TSDictN
1895 make_specialized_arrmap(BSDictN, {map_elem(s_A, TSStr)})
1897 EXPECT_EQ(
1898 intersection_of(
1899 make_specialized_arrmap(BDictN, {map_elem_nonstatic(s_A, TStr)}),
1900 TSDictN
1902 make_specialized_arrmap(BSDictN, {map_elem(s_A, TSStr)})
1904 EXPECT_EQ(
1905 intersection_of(
1906 make_specialized_arrmap(BDictN, {map_elem_counted(s_A, TStr)}),
1907 TSDictN
1909 TBottom
1911 EXPECT_EQ(
1912 intersection_of(
1913 make_specialized_arrmap(BDictN, {map_elem(123, TStr)}),
1914 TSDictN
1916 make_specialized_arrmap(BSDictN, {map_elem(123, TSStr)})
1919 EXPECT_EQ(
1920 intersection_of(
1921 make_specialized_arrmap(BCDictN|BKeysetN, {map_elem(s_A, TArrKey)}),
1922 make_specialized_arrmap(BSDictN|BKeysetN, {map_elem(s_A, TArrKey)})
1924 make_specialized_arrmap(BKeysetN, {map_elem(s_A, sval(s_A))})
1926 EXPECT_EQ(
1927 intersection_of(
1928 make_specialized_arrmap(BCDictN|BKeysetN, {map_elem_nonstatic(s_A, sval(s_A))}),
1929 make_specialized_arrmap(BSDictN|BKeysetN, {map_elem_nonstatic(s_A, sval(s_A))})
1931 make_specialized_arrmap(BKeysetN, {map_elem(s_A, sval(s_A))})
1933 EXPECT_EQ(
1934 intersection_of(
1935 make_specialized_arrmap(BSDictN|BKeysetN, {map_elem(s_A, TArrKey)}),
1936 make_specialized_arrmap(BCDictN|BKeysetN, {map_elem_nonstatic(s_A, TCStr)})
1938 TBottom
1941 EXPECT_EQ(
1942 intersection_of(
1943 make_specialized_arrmap(BDictN|BKeysetN, {map_elem_counted(s_A, TCStr)}),
1944 Type{BDictN|BSKeysetN}
1946 make_specialized_arrmap(BDictN, {map_elem_counted(s_A, TCStr)})
1948 EXPECT_EQ(
1949 intersection_of(
1950 make_specialized_arrmap(BDictN|BKeysetN, {map_elem_nonstatic(s_A, TCStr)}),
1951 make_specialized_arrmap(BDictN|BSKeysetN, {map_elem(s_A, TArrKey)})
1953 make_specialized_arrmap(BDictN, {map_elem(s_A, TCStr)})
1956 EXPECT_EQ(
1957 intersection_of(
1958 make_specialized_arrmap(BDictN, {map_elem(s_A, TInitCell)}, TArrKey, TInitCell),
1959 make_specialized_arrmap(BSDictN|BKeysetN, {map_elem(s_A, TArrKey)}, TArrKey, TArrKey)
1961 make_specialized_arrmap(BSDictN, {map_elem(s_A, TUncArrKey)}, TUncArrKey, TUncArrKey)
1964 EXPECT_EQ(
1965 intersection_of(
1966 make_specialized_arrpackedn(BVecN|BKeysetN, ival(0)),
1967 TKeyset
1969 make_specialized_arrpacked(BKeysetN, {ival(0)})
1973 TEST(Type, Split) {
1974 auto const program = make_test_program();
1975 Index index { program.get() };
1977 auto const test = [] (auto f, trep bits, const Type& split,
1978 const Type& rest, const Type& orig) {
1979 EXPECT_TRUE(split.moreRefined(orig));
1980 EXPECT_TRUE(rest.moreRefined(orig));
1981 EXPECT_FALSE(split.couldBe(rest));
1982 EXPECT_TRUE(union_of(split, rest).equivalentlyRefined(orig));
1984 if (orig.couldBe(bits)) {
1985 EXPECT_TRUE(split.subtypeOf(bits));
1986 } else {
1987 EXPECT_EQ(split, TBottom);
1989 EXPECT_FALSE(rest.couldBe(bits));
1990 if (orig.subtypeOf(bits)) {
1991 EXPECT_EQ(rest, TBottom);
1994 if (f(orig)) {
1995 EXPECT_TRUE(f(split));
1996 EXPECT_FALSE(rest.hasData());
1997 } else if (orig.hasData()) {
1998 EXPECT_FALSE(split.hasData());
1999 EXPECT_TRUE(rest.hasData());
2000 } else {
2001 EXPECT_FALSE(split.hasData());
2002 EXPECT_FALSE(rest.hasData());
2006 auto const& types = allCases(index);
2007 for (auto const& t : types) {
2008 if (!t.subtypeOf(BCell)) continue;
2010 auto const [obj, objRest] = split_obj(t);
2011 test(is_specialized_obj, BObj, obj, objRest, t);
2013 auto const [cls, clsRest] = split_cls(t);
2014 test(is_specialized_cls, BCls, cls, clsRest, t);
2016 auto const [arr, arrRest] = split_array_like(t);
2017 test(is_specialized_array_like, BArrLike, arr, arrRest, t);
2019 auto const [str, strRest] = split_string(t);
2020 test(is_specialized_string, BStr, str, strRest, t);
2022 auto const [lcls, lclsRest] = split_lazycls(t);
2023 test(is_specialized_lazycls, BLazyCls, lcls, lclsRest, t);
2026 auto split = split_array_like(Type{BDictN|BInt});
2027 EXPECT_EQ(split.first, TDictN);
2028 EXPECT_EQ(split.second, TInt);
2030 split = split_array_like(TVecE);
2031 EXPECT_EQ(split.first, TVecE);
2032 EXPECT_EQ(split.second, TBottom);
2034 split = split_array_like(TInt);
2035 EXPECT_EQ(split.first, TBottom);
2036 EXPECT_EQ(split.second, TInt);
2038 split = split_array_like(ival(123));
2039 EXPECT_EQ(split.first, TBottom);
2040 EXPECT_EQ(split.second, ival(123));
2042 split = split_array_like(union_of(TKeyset,ival(123)));
2043 EXPECT_EQ(split.first, TKeyset);
2044 EXPECT_EQ(split.second, TInt);
2046 split = split_array_like(make_specialized_arrmapn(BDictN, TStr, TObj));
2047 EXPECT_EQ(split.first, make_specialized_arrmapn(BDictN, TStr, TObj));
2048 EXPECT_EQ(split.second, TBottom);
2050 split = split_array_like(make_specialized_arrmapn(BDictN|BFalse, TStr, TObj));
2051 EXPECT_EQ(split.first, make_specialized_arrmapn(BDictN, TStr, TObj));
2052 EXPECT_EQ(split.second, TFalse);
2054 auto const clsA = index.resolve_class(Context{}, s_A.get());
2055 if (!clsA || !clsA->resolved()) ADD_FAILURE();
2057 split = split_obj(Type{BObj|BInt});
2058 EXPECT_EQ(split.first, TObj);
2059 EXPECT_EQ(split.second, TInt);
2061 split = split_obj(TObj);
2062 EXPECT_EQ(split.first, TObj);
2063 EXPECT_EQ(split.second, TBottom);
2065 split = split_obj(TInt);
2066 EXPECT_EQ(split.first, TBottom);
2067 EXPECT_EQ(split.second, TInt);
2069 split = split_obj(ival(123));
2070 EXPECT_EQ(split.first, TBottom);
2071 EXPECT_EQ(split.second, ival(123));
2073 split = split_obj(union_of(TObj,ival(123)));
2074 EXPECT_EQ(split.first, TObj);
2075 EXPECT_EQ(split.second, TInt);
2077 split = split_obj(make_specialized_sub_object(BObj, *clsA));
2078 EXPECT_EQ(split.first, make_specialized_sub_object(BObj, *clsA));
2079 EXPECT_EQ(split.second, TBottom);
2081 split = split_obj(make_specialized_sub_object(BObj|BFalse, *clsA));
2082 EXPECT_EQ(split.first, make_specialized_sub_object(BObj, *clsA));
2083 EXPECT_EQ(split.second, TFalse);
2085 split = split_cls(Type{BCls|BInt});
2086 EXPECT_EQ(split.first, TCls);
2087 EXPECT_EQ(split.second, TInt);
2089 split = split_cls(TCls);
2090 EXPECT_EQ(split.first, TCls);
2091 EXPECT_EQ(split.second, TBottom);
2093 split = split_cls(TInt);
2094 EXPECT_EQ(split.first, TBottom);
2095 EXPECT_EQ(split.second, TInt);
2097 split = split_cls(ival(123));
2098 EXPECT_EQ(split.first, TBottom);
2099 EXPECT_EQ(split.second, ival(123));
2101 split = split_cls(union_of(TCls,ival(123)));
2102 EXPECT_EQ(split.first, TCls);
2103 EXPECT_EQ(split.second, TInt);
2105 split = split_cls(make_specialized_sub_class(BCls, *clsA));
2106 EXPECT_EQ(split.first, make_specialized_sub_class(BCls, *clsA));
2107 EXPECT_EQ(split.second, TBottom);
2109 split = split_cls(make_specialized_sub_class(BCls|BFalse, *clsA));
2110 EXPECT_EQ(split.first, make_specialized_sub_class(BCls, *clsA));
2111 EXPECT_EQ(split.second, TFalse);
2113 split = split_string(TStr);
2114 EXPECT_EQ(split.first, TStr);
2115 EXPECT_EQ(split.second, TBottom);
2117 split = split_string(TInt);
2118 EXPECT_EQ(split.first, TBottom);
2119 EXPECT_EQ(split.second, TInt);
2121 split = split_string(sval(s_A));
2122 EXPECT_EQ(split.first, sval(s_A));
2123 EXPECT_EQ(split.second, TBottom);
2125 split = split_string(ival(123));
2126 EXPECT_EQ(split.first, TBottom);
2127 EXPECT_EQ(split.second, ival(123));
2129 split = split_string(Type{BStr|BInt});
2130 EXPECT_EQ(split.first, TStr);
2131 EXPECT_EQ(split.second, TInt);
2133 split = split_string(union_of(sval(s_A), TFalse));
2134 EXPECT_EQ(split.first, sval(s_A));
2135 EXPECT_EQ(split.second, TFalse);
2137 split = split_string(union_of(TStr, ival(123)));
2138 EXPECT_EQ(split.first, TStr);
2139 EXPECT_EQ(split.second, TInt);
2141 split = split_lazycls(TInt);
2142 EXPECT_EQ(split.first, TBottom);
2143 EXPECT_EQ(split.second, TInt);
2145 split = split_lazycls(Type{BStr|BLazyCls});
2146 EXPECT_EQ(split.first, TLazyCls);
2147 EXPECT_EQ(split.second, TStr);
2149 split = split_lazycls(union_of(lazyclsval(s_A), TFalse));
2150 EXPECT_EQ(split.first, lazyclsval(s_A));
2151 EXPECT_EQ(split.second, TFalse);
2154 TEST(Type, Remove) {
2155 auto const program = make_test_program();
2156 Index index { program.get() };
2158 auto const test = [] (auto f, trep bits, const Type& removed,
2159 const Type& orig) {
2160 EXPECT_TRUE(removed.moreRefined(orig));
2161 if (orig.couldBe(bits)) {
2162 EXPECT_TRUE(removed.strictlyMoreRefined(orig));
2164 EXPECT_FALSE(removed.couldBe(bits));
2166 if (f(orig) || !orig.hasData()) {
2167 EXPECT_FALSE(removed.hasData());
2168 } else {
2169 EXPECT_TRUE(removed.hasData());
2173 auto const& types = allCases(index);
2174 for (auto const& t : types) {
2175 if (!t.subtypeOf(BCell)) continue;
2176 test(is_specialized_int, BInt, remove_int(t), t);
2177 test(is_specialized_double, BDbl, remove_double(t), t);
2178 test(is_specialized_string, BStr, remove_string(t), t);
2179 test(is_specialized_lazycls, BLazyCls, remove_lazycls(t), t);
2180 test(is_specialized_cls, BCls, remove_cls(t), t);
2181 test(is_specialized_obj, BObj, remove_obj(t), t);
2183 EXPECT_EQ(remove_int(t), remove_bits(t, BInt));
2184 EXPECT_EQ(remove_double(t), remove_bits(t, BDbl));
2185 EXPECT_EQ(remove_string(t), remove_bits(t, BStr));
2186 EXPECT_EQ(remove_lazycls(t), remove_bits(t, BLazyCls));
2187 EXPECT_EQ(remove_cls(t), remove_bits(t, BCls));
2188 EXPECT_EQ(remove_obj(t), remove_bits(t, BObj));
2190 EXPECT_FALSE(is_specialized_array_like(remove_bits(t, BArrLikeN)));
2191 if (t.couldBe(BDictN)) {
2192 EXPECT_FALSE(is_specialized_array_like(remove_bits(t, BDictN)));
2195 EXPECT_FALSE(remove_keyset(t).couldBe(BKeyset));
2196 if (!t.couldBe(BKeyset)) {
2197 EXPECT_EQ(remove_keyset(t), t);
2199 if (t.subtypeAmong(BKeyset, BArrLike)) {
2200 EXPECT_FALSE(is_specialized_array_like(remove_keyset(t)));
2204 EXPECT_EQ(remove_int(TStr), TStr);
2205 EXPECT_EQ(remove_int(TInt), TBottom);
2206 EXPECT_EQ(remove_int(Type{BStr|BInt}), TStr);
2207 EXPECT_EQ(remove_int(ival(123)), TBottom);
2208 EXPECT_EQ(remove_int(dval(1.23)), dval(1.23));
2209 EXPECT_EQ(remove_int(union_of(ival(123),TDbl)), TDbl);
2210 EXPECT_EQ(remove_int(union_of(TInt,dval(1.23))), TDbl);
2212 EXPECT_EQ(remove_double(TStr), TStr);
2213 EXPECT_EQ(remove_double(TDbl), TBottom);
2214 EXPECT_EQ(remove_double(Type{BStr|BDbl}), TStr);
2215 EXPECT_EQ(remove_double(dval(1.23)), TBottom);
2216 EXPECT_EQ(remove_double(ival(123)), ival(123));
2217 EXPECT_EQ(remove_double(union_of(ival(123),TDbl)), TInt);
2218 EXPECT_EQ(remove_double(union_of(TInt,dval(1.23))), TInt);
2220 EXPECT_EQ(remove_string(TInt), TInt);
2221 EXPECT_EQ(remove_string(TStr), TBottom);
2222 EXPECT_EQ(remove_string(Type{BStr|BInt}), TInt);
2223 EXPECT_EQ(remove_string(ival(123)), ival(123));
2224 EXPECT_EQ(remove_string(sval(s_A)), TBottom);
2225 EXPECT_EQ(remove_string(union_of(ival(123),TStr)), TInt);
2226 EXPECT_EQ(remove_string(union_of(TInt,sval(s_A))), TInt);
2228 EXPECT_EQ(remove_lazycls(TStr), TStr);
2229 EXPECT_EQ(remove_lazycls(TLazyCls), TBottom);
2230 EXPECT_EQ(remove_lazycls(Type{BLazyCls|BStr}), TStr);
2231 EXPECT_EQ(remove_lazycls(lazyclsval(s_A)), TBottom);
2232 EXPECT_EQ(remove_lazycls(union_of(TInt,lazyclsval(s_A))), TInt);
2234 auto const clsA = index.resolve_class(Context{}, s_A.get());
2235 if (!clsA || !clsA->resolved()) ADD_FAILURE();
2237 EXPECT_EQ(remove_cls(TInt), TInt);
2238 EXPECT_EQ(remove_cls(TCls), TBottom);
2239 EXPECT_EQ(remove_cls(Type{BCls|BInt}), TInt);
2240 EXPECT_EQ(remove_cls(ival(123)), ival(123));
2241 EXPECT_EQ(remove_cls(make_specialized_sub_class(BCls, *clsA)), TBottom);
2242 EXPECT_EQ(remove_cls(union_of(ival(123),TCls)), TInt);
2243 EXPECT_EQ(remove_cls(make_specialized_sub_class(BCls|BFalse, *clsA)), TFalse);
2245 EXPECT_EQ(remove_obj(TInt), TInt);
2246 EXPECT_EQ(remove_obj(TObj), TBottom);
2247 EXPECT_EQ(remove_obj(Type{BInt|BObj}), TInt);
2248 EXPECT_EQ(remove_obj(ival(123)), ival(123));
2249 EXPECT_EQ(remove_obj(make_specialized_sub_object(BObj, *clsA)), TBottom);
2250 EXPECT_EQ(remove_obj(union_of(ival(123),TObj)), TInt);
2251 EXPECT_EQ(remove_obj(make_specialized_sub_object(BObj|BFalse, *clsA)), TFalse);
2254 TEST(Type, Prim) {
2255 const std::initializer_list<std::pair<Type, Type>> subtype_true{
2256 { TInt, TPrim },
2257 { TBool, TPrim },
2258 { TNum, TPrim },
2259 { TInitNull, TPrim },
2260 { TDbl, TPrim },
2261 { dval(0.0), TPrim },
2262 { ival(0), TPrim },
2263 { TNull, TPrim },
2264 { TInt, TInitPrim },
2265 { TBool, TInitPrim },
2266 { TNum, TInitPrim },
2267 { TInitNull, TInitPrim },
2268 { TDbl, TInitPrim },
2269 { dval(0.0), TInitPrim },
2270 { ival(0), TInitPrim },
2273 const std::initializer_list<std::pair<Type, Type>> subtype_false{
2274 { sval(s_test), TPrim },
2275 { TSStr, TPrim },
2276 { TNull, TInitPrim }, // TNull could be uninit
2277 { TPrim, TBool },
2278 { TPrim, TInt },
2279 { TPrim, TNum },
2280 { TInitPrim, TNum },
2281 { TUnc, TPrim },
2282 { TUnc, TInitPrim },
2283 { TInitUnc, TPrim },
2284 { TSStr, TInitPrim },
2285 { TRes, TPrim },
2286 { TObj, TPrim },
2287 { TRFunc, TPrim },
2288 { TPrim, dval(0.0) },
2289 { TCls, TInitPrim },
2290 { TFunc, TInitPrim },
2291 { TLazyCls, TInitPrim },
2294 const std::initializer_list<std::pair<Type, Type>> couldbe_true{
2295 { TPrim, TInt },
2296 { TPrim, TBool },
2297 { TPrim, TNum },
2298 { TInitPrim, TNum },
2299 { TInitPrim, TFalse },
2300 { TPrim, TCell },
2301 { TPrim, TOptObj },
2302 { TPrim, TOptFalse },
2305 const std::initializer_list<std::pair<Type, Type>> couldbe_false{
2306 { TPrim, TSStr },
2307 { TInitPrim, TSStr },
2308 { TInitPrim, sval(s_test) },
2309 { TInitPrim, lazyclsval(s_test) },
2310 { TPrim, sval(s_test) },
2311 { TInitPrim, TUninit },
2312 { TPrim, TObj },
2313 { TPrim, TRes },
2314 { TPrim, TRFunc },
2315 { TPrim, TFunc },
2318 for (auto kv : subtype_true) {
2319 EXPECT_TRUE(kv.first.subtypeOf(kv.second))
2320 << show(kv.first) << " subtypeOf " << show(kv.second);
2323 for (auto kv : subtype_false) {
2324 EXPECT_FALSE(kv.first.subtypeOf(kv.second))
2325 << show(kv.first) << " !subtypeOf " << show(kv.second);
2328 for (auto kv : couldbe_true) {
2329 EXPECT_TRUE(kv.first.couldBe(kv.second))
2330 << show(kv.first) << " couldbe " << show(kv.second);
2331 EXPECT_TRUE(kv.second.couldBe(kv.first))
2332 << show(kv.first) << " couldbe " << show(kv.second);
2335 for (auto kv : couldbe_false) {
2336 EXPECT_FALSE(kv.first.couldBe(kv.second))
2337 << show(kv.first) << " !couldbe " << show(kv.second);
2338 EXPECT_FALSE(kv.second.couldBe(kv.first))
2339 << show(kv.first) << " !couldbe " << show(kv.second);
2342 EXPECT_FALSE(TClsMeth.subtypeOf(TInitPrim));
2343 EXPECT_FALSE(TPrim.couldBe(TClsMeth));
2346 TEST(Type, CouldBeValues) {
2347 EXPECT_FALSE(ival(2).couldBe(ival(3)));
2348 EXPECT_TRUE(ival(2).couldBe(ival(2)));
2350 auto const packed_dict = static_dict(0, 42, 1, 23, 2, 12);
2351 auto const dict = static_dict(s_A.get(), s_B.get(), s_test.get(), 12);
2353 EXPECT_FALSE(dict_val(packed_dict).couldBe(dict_val(dict)));
2354 EXPECT_TRUE(dict_val(packed_dict).couldBe(dict_val(packed_dict)));
2355 EXPECT_TRUE(dval(2.0).couldBe(dval(2.0)));
2356 EXPECT_FALSE(dval(2.0).couldBe(dval(3.0)));
2358 EXPECT_FALSE(sval(s_test).couldBe(sval(s_A)));
2359 EXPECT_TRUE(sval(s_test).couldBe(sval(s_test)));
2360 EXPECT_FALSE(
2361 sval_nonstatic(s_test).couldBe(sval_nonstatic(s_A))
2363 EXPECT_TRUE(
2364 sval_nonstatic(s_test).couldBe(sval_nonstatic(s_test))
2366 EXPECT_TRUE(sval(s_test).couldBe(sval_nonstatic(s_test)));
2367 EXPECT_TRUE(sval_nonstatic(s_test).couldBe(sval(s_test)));
2368 EXPECT_FALSE(sval(s_test.get()).couldBe(sval_nonstatic(s_A)));
2369 EXPECT_FALSE(sval_nonstatic(s_test).couldBe(sval(s_A)));
2371 EXPECT_FALSE(lazyclsval(s_test).couldBe(lazyclsval(s_A)));
2372 EXPECT_TRUE(lazyclsval(s_test).couldBe(lazyclsval(s_test)));
2375 TEST(Type, Unc) {
2376 EXPECT_TRUE(TInt.subtypeOf(BInitUnc));
2377 EXPECT_TRUE(TInt.subtypeOf(BUnc));
2378 EXPECT_TRUE(TDbl.subtypeOf(BInitUnc));
2379 EXPECT_TRUE(TDbl.subtypeOf(BUnc));
2380 EXPECT_TRUE(dval(3.0).subtypeOf(BInitUnc));
2381 EXPECT_TRUE(TClsMeth.subtypeOf(BInitUnc));
2383 const std::initializer_list<std::tuple<Type, Type, bool>> tests{
2384 { TUnc, TInitUnc, true },
2385 { TUnc, TInitCell, true },
2386 { TUnc, TCell, true },
2387 { TInitUnc, TInt, true },
2388 { TInitUnc, TOptInt, true },
2389 { TInitUnc, opt(ival(2)), true },
2390 { TUnc, TInt, true },
2391 { TUnc, TOptInt, true },
2392 { TUnc, opt(ival(2)), true },
2393 { TNum, TUnc, true },
2394 { TNum, TInitUnc, true },
2395 { TUncArrKey, TInitUnc, true },
2396 { TClsMeth, TInitUnc, true },
2398 for (auto const& t : tests) {
2399 auto const& ty1 = std::get<0>(t);
2400 auto const& ty2 = std::get<1>(t);
2401 if (std::get<2>(t)) {
2402 EXPECT_TRUE(ty1.couldBe(ty2))
2403 << show(ty1) << " couldBe " << show(ty2);
2404 } else {
2405 EXPECT_FALSE(ty1.couldBe(ty2))
2406 << show(ty1) << " !couldBe " << show(ty2);
2411 TEST(Type, DblNan) {
2412 auto const qnan = std::numeric_limits<double>::quiet_NaN();
2413 EXPECT_TRUE(dval(qnan).subtypeOf(dval(qnan)));
2414 EXPECT_TRUE(dval(qnan).couldBe(dval(qnan)));
2415 EXPECT_FALSE(dval(qnan).strictSubtypeOf(dval(qnan)));
2416 EXPECT_EQ(dval(qnan), dval(qnan));
2417 EXPECT_EQ(union_of(dval(qnan), dval(qnan)), dval(qnan));
2418 EXPECT_EQ(intersection_of(dval(qnan), dval(qnan)), dval(qnan));
2421 TEST(Type, ToObj) {
2422 auto const program = make_test_program();
2423 Index index { program.get() };
2425 auto const& all = allCases(index);
2426 for (auto const& t : all) {
2427 if (t.is(BBottom) || !t.subtypeOf(BCls)) continue;
2428 EXPECT_TRUE(toobj(t).subtypeOf(BObj));
2429 if (!is_specialized_cls(t)) {
2430 EXPECT_EQ(toobj(t), TObj);
2431 } else {
2432 EXPECT_TRUE(is_specialized_obj(toobj(t)));
2436 for (auto const& t : all) {
2437 if (t.is(BBottom) || !t.subtypeOf(BObj)) continue;
2438 EXPECT_TRUE(objcls(t).subtypeOf(BCls));
2439 if (!is_specialized_obj(t)) {
2440 EXPECT_EQ(objcls(t), TCls);
2441 } else {
2442 EXPECT_TRUE(is_specialized_cls(objcls(t)));
2446 auto const clsA = index.resolve_class(Context{}, s_A.get());
2447 if (!clsA || !clsA->resolved()) ADD_FAILURE();
2449 auto const awaitable = index.builtin_class(s_Awaitable.get());
2451 EXPECT_EQ(toobj(TCls), TObj);
2452 EXPECT_EQ(toobj(make_specialized_sub_class(BCls, *clsA)),
2453 make_specialized_sub_object(BObj, *clsA));
2454 EXPECT_EQ(toobj(make_specialized_exact_class(BCls, *clsA)),
2455 make_specialized_exact_object(BObj, *clsA));
2457 EXPECT_EQ(objcls(TObj), TCls);
2458 EXPECT_EQ(objcls(make_specialized_sub_object(BObj, *clsA)),
2459 make_specialized_sub_class(BCls, *clsA));
2460 EXPECT_EQ(objcls(make_specialized_exact_object(BObj, *clsA)),
2461 make_specialized_exact_class(BCls, *clsA));
2462 EXPECT_EQ(objcls(make_specialized_wait_handle(BObj, TInt, index)),
2463 make_specialized_sub_class(BCls, awaitable));
2466 TEST(Type, Option) {
2467 auto const program = make_test_program();
2468 Index index { program.get() };
2470 EXPECT_TRUE(TTrue.subtypeOf(BOptTrue));
2471 EXPECT_TRUE(TInitNull.subtypeOf(BOptTrue));
2472 EXPECT_TRUE(!TUninit.subtypeOf(BOptTrue));
2474 EXPECT_TRUE(TFalse.subtypeOf(BOptFalse));
2475 EXPECT_TRUE(TInitNull.subtypeOf(BOptFalse));
2476 EXPECT_TRUE(!TUninit.subtypeOf(BOptFalse));
2478 EXPECT_TRUE(TFalse.subtypeOf(BOptBool));
2479 EXPECT_TRUE(TTrue.subtypeOf(BOptBool));
2480 EXPECT_TRUE(TInitNull.subtypeOf(BOptBool));
2481 EXPECT_TRUE(!TUninit.subtypeOf(BOptBool));
2483 EXPECT_TRUE(ival(3).subtypeOf(BOptInt));
2484 EXPECT_TRUE(TInt.subtypeOf(BOptInt));
2485 EXPECT_TRUE(TInitNull.subtypeOf(BOptInt));
2486 EXPECT_TRUE(!TUninit.subtypeOf(BOptInt));
2488 EXPECT_TRUE(TDbl.subtypeOf(BOptDbl));
2489 EXPECT_TRUE(TInitNull.subtypeOf(BOptDbl));
2490 EXPECT_TRUE(!TUninit.subtypeOf(BOptDbl));
2491 EXPECT_TRUE(dval(3.0).subtypeOf(BOptDbl));
2493 EXPECT_TRUE(sval(s_test).subtypeOf(BOptSStr));
2494 EXPECT_TRUE(sval(s_test).subtypeOf(BOptStr));
2495 EXPECT_TRUE(sval_nonstatic(s_test).subtypeOf(BOptStr));
2496 EXPECT_TRUE(TSStr.subtypeOf(BOptSStr));
2497 EXPECT_TRUE(TInitNull.subtypeOf(BOptSStr));
2498 EXPECT_TRUE(!TUninit.subtypeOf(BOptSStr));
2499 EXPECT_TRUE(!TStr.subtypeOf(BOptSStr));
2500 EXPECT_TRUE(TStr.couldBe(BOptSStr));
2502 EXPECT_TRUE(TStr.subtypeOf(BOptStr));
2503 EXPECT_TRUE(TSStr.subtypeOf(BOptStr));
2504 EXPECT_TRUE(sval(s_test).subtypeOf(BOptStr));
2505 EXPECT_TRUE(TInitNull.subtypeOf(BOptStr));
2506 EXPECT_TRUE(!TUninit.subtypeOf(BOptStr));
2508 EXPECT_TRUE(lazyclsval(s_test).subtypeOf(BOptLazyCls));
2509 EXPECT_TRUE(TLazyCls.subtypeOf(BOptLazyCls));
2510 EXPECT_TRUE(TInitNull.subtypeOf(BOptLazyCls));
2511 EXPECT_TRUE(!TUninit.subtypeOf(BOptLazyCls));
2513 EXPECT_TRUE(TObj.subtypeOf(BOptObj));
2514 EXPECT_TRUE(TInitNull.subtypeOf(BOptObj));
2515 EXPECT_TRUE(!TUninit.subtypeOf(BOptObj));
2517 EXPECT_TRUE(TRes.subtypeOf(BOptRes));
2518 EXPECT_TRUE(TInitNull.subtypeOf(BOptRes));
2519 EXPECT_TRUE(!TUninit.subtypeOf(BOptRes));
2521 EXPECT_TRUE(TClsMeth.subtypeOf(BOptClsMeth));
2522 EXPECT_TRUE(TInitNull.subtypeOf(BOptClsMeth));
2523 EXPECT_TRUE(!TUninit.subtypeOf(BOptClsMeth));
2525 EXPECT_TRUE(TRClsMeth.subtypeOf(BOptRClsMeth));
2526 EXPECT_TRUE(TInitNull.subtypeOf(BOptRClsMeth));
2527 EXPECT_TRUE(!TUninit.subtypeOf(BOptRClsMeth));
2529 EXPECT_TRUE(TLazyCls.subtypeOf(BOptLazyCls));
2530 EXPECT_TRUE(TInitNull.subtypeOf(BOptLazyCls));
2531 EXPECT_TRUE(!TUninit.subtypeOf(BOptLazyCls));
2533 EXPECT_TRUE(TArrKey.subtypeOf(BOptArrKey));
2534 EXPECT_TRUE(TInitNull.subtypeOf(BOptArrKey));
2535 EXPECT_TRUE(!TUninit.subtypeOf(BOptArrKey));
2537 for (auto const& t : optionals()) {
2538 EXPECT_EQ(t, opt(unopt(t)));
2541 EXPECT_TRUE(wait_handle(index, opt(dval(2.0))).couldBe(
2542 wait_handle(index, dval(2.0))));
2545 TEST(Type, OptUnionOf) {
2546 EXPECT_EQ(opt(ival(2)), union_of(ival(2), TInitNull));
2547 EXPECT_EQ(opt(dval(2.0)), union_of(TInitNull, dval(2.0)));
2548 EXPECT_EQ(opt(sval(s_test)), union_of(sval(s_test), TInitNull));
2549 EXPECT_EQ(opt(lazyclsval(s_test)), union_of(lazyclsval(s_test), TInitNull));
2550 EXPECT_EQ(opt(sval_nonstatic(s_test)),
2551 union_of(sval_nonstatic(s_test), TInitNull));
2552 EXPECT_EQ(opt(sval(s_test)), union_of(TInitNull, sval(s_test)));
2553 EXPECT_EQ(opt(lazyclsval(s_test)), union_of(TInitNull, lazyclsval(s_test)));
2554 EXPECT_EQ(opt(sval_nonstatic(s_test)),
2555 union_of(TInitNull, sval_nonstatic(s_test)));
2557 EXPECT_EQ(TOptBool, union_of(TOptFalse, TOptTrue));
2558 EXPECT_EQ(TOptBool, union_of(TOptTrue, TOptFalse));
2560 EXPECT_EQ(TOptSStr,
2561 union_of(opt(sval(s_test)), opt(sval(s_TestClass))));
2562 EXPECT_EQ(TOptStr,
2563 union_of(opt(sval_nonstatic(s_test)),
2564 opt(sval_nonstatic(s_TestClass))));
2566 EXPECT_EQ(TOptInt, union_of(opt(ival(2)), opt(ival(3))));
2567 EXPECT_EQ(TOptDbl, union_of(opt(dval(2.0)), opt(dval(3.0))));
2568 EXPECT_EQ(TOptNum, union_of(TInitNull, TNum));
2570 EXPECT_EQ(TOptTrue, union_of(TInitNull, TTrue));
2571 EXPECT_EQ(TOptFalse, union_of(TInitNull, TFalse));
2572 EXPECT_EQ(TOptRes, union_of(TInitNull, TRes));
2574 EXPECT_EQ(TOptTrue, union_of(TOptTrue, TTrue));
2575 EXPECT_EQ(TOptFalse, union_of(TOptFalse, TFalse));
2576 EXPECT_EQ(TOptBool, union_of(TOptTrue, TFalse));
2578 EXPECT_EQ(TOptClsMeth, union_of(TInitNull, TClsMeth));
2579 EXPECT_EQ(TOptRClsMeth, union_of(TInitNull, TRClsMeth));
2581 auto const program = make_test_program();
2582 Index index { program.get() };
2583 auto const rcls = index.builtin_class(s_Awaitable.get());
2585 EXPECT_TRUE(union_of(TObj, opt(objExact(rcls))) == TOptObj);
2587 auto wh1 = wait_handle(index, TInt);
2588 auto wh2 = wait_handle(index, ival(2));
2589 auto wh3 = wait_handle(index, ival(3));
2591 EXPECT_TRUE(union_of(wh1, wh2) == wh1);
2592 auto owh1 = opt(wh1);
2593 auto owh2 = opt(wh2);
2594 auto owh3 = opt(wh3);
2596 EXPECT_TRUE(union_of(owh1, owh2) == owh1);
2597 EXPECT_TRUE(union_of(owh1, wh2) == owh1);
2598 EXPECT_TRUE(union_of(owh2, wh1) == owh1);
2600 EXPECT_TRUE(union_of(wh1, owh2) == owh1);
2601 EXPECT_TRUE(union_of(wh2, owh1) == owh1);
2603 EXPECT_TRUE(union_of(wh2, owh3) == owh1);
2604 EXPECT_TRUE(union_of(owh2, wh3) == owh1);
2607 TEST(Type, TV) {
2608 auto const program = make_test_program();
2609 Index index { program.get() };
2611 auto const& all = allCases(index);
2612 for (auto const& t : all) {
2613 EXPECT_EQ(is_scalar(t), tv(t).has_value());
2614 if (!t.hasData() && !t.subtypeOf(BNull | BBool | BArrLikeE)) {
2615 EXPECT_FALSE(tv(t).has_value());
2618 if (t.couldBe(BCounted & ~(BArrLike | BStr)) ||
2619 (t.couldBe(BStr) && t.subtypeAmong(BCStr, BStr)) ||
2620 (t.couldBe(BVec) && t.subtypeAmong(BCVec, BVec)) ||
2621 (t.couldBe(BDict) && t.subtypeAmong(BCDict, BDict)) ||
2622 (t.couldBe(BKeyset) && t.subtypeAmong(BCKeyset, BKeyset))) {
2623 EXPECT_FALSE(is_scalar(t));
2624 EXPECT_FALSE(tv(t).has_value());
2627 if (t.couldBe(BInitNull) && !t.subtypeOf(BInitNull)) {
2628 EXPECT_FALSE(tv(t).has_value());
2631 if (!t.subtypeOf(BInitNull)) {
2632 EXPECT_FALSE(is_scalar(opt(t)));
2633 EXPECT_FALSE(tv(opt(t)).has_value());
2636 if (t.couldBe(BArrLikeE)) {
2637 if (!t.subtypeAmong(BVecE, BArrLike) &&
2638 !t.subtypeAmong(BDictE, BArrLike) &&
2639 !t.subtypeAmong(BKeysetE, BArrLike)) {
2640 EXPECT_FALSE(tv(t).has_value());
2645 auto const test = [&] (const Type& t, TypedValue d) {
2646 auto const val = tv(t);
2647 EXPECT_TRUE(val && tvSame(*val, d));
2649 test(TUninit, make_tv<KindOfUninit>());
2650 test(TInitNull, make_tv<KindOfNull>());
2651 test(TTrue, make_tv<KindOfBoolean>(true));
2652 test(TFalse, make_tv<KindOfBoolean>(false));
2653 test(vec_empty(), make_array_like_tv(staticEmptyVec()));
2654 test(some_vec_empty(), make_array_like_tv(staticEmptyVec()));
2655 test(dict_empty(), make_array_like_tv(staticEmptyDictArray()));
2656 test(some_dict_empty(), make_array_like_tv(staticEmptyDictArray()));
2657 test(keyset_empty(), make_array_like_tv(staticEmptyKeysetArray()));
2658 test(some_keyset_empty(), make_array_like_tv(staticEmptyKeysetArray()));
2659 test(ival(123), make_tv<KindOfInt64>(123));
2660 test(dval(3.141), make_tv<KindOfDouble>(3.141));
2661 test(sval(s_A), tv(s_A));
2662 test(lazyclsval(s_A), tv(s_A));
2663 test(vec_val(static_vec(123, 456, 789)),
2664 make_array_like_tv(const_cast<ArrayData*>(static_vec(123, 456, 789))));
2665 test(make_specialized_arrpacked(BDictN, {ival(1), ival(2), ival(3)}, LegacyMark::Unmarked),
2666 make_array_like_tv(const_cast<ArrayData*>(static_dict(0, 1, 1, 2, 2, 3))));
2667 test(make_specialized_arrpacked(BKeysetN, {ival(0), ival(1)}),
2668 make_array_like_tv(const_cast<ArrayData*>(static_keyset(0, 1))));
2670 test(
2671 make_specialized_arrmap(
2672 BDictN,
2673 {map_elem(s_A, ival(1)), map_elem(s_B, ival(2))},
2674 TBottom, TBottom,
2675 LegacyMark::Unmarked
2677 make_array_like_tv(const_cast<ArrayData*>(static_dict(s_A.get(), 1, s_B.get(), 2)))
2679 test(
2680 make_specialized_arrmap(
2681 BDictN,
2682 {map_elem_nonstatic(s_A, ival(1)), map_elem_nonstatic(s_B, ival(2))},
2683 TBottom, TBottom,
2684 LegacyMark::Unmarked
2686 make_array_like_tv(const_cast<ArrayData*>(static_dict(s_A.get(), 1, s_B.get(), 2)))
2689 EXPECT_FALSE(tv(TOptTrue).has_value());
2690 EXPECT_FALSE(tv(TOptFalse).has_value());
2691 EXPECT_FALSE(tv(TNull).has_value());
2692 EXPECT_FALSE(tv(union_of(dict_empty(), vec_empty())).has_value());
2693 EXPECT_FALSE(tv(make_specialized_int(BInt|BFalse, 123)).has_value());
2694 EXPECT_FALSE(tv(make_specialized_string(BStr|BFalse, s_A.get())).has_value());
2695 EXPECT_FALSE(tv(make_specialized_lazycls(BLazyCls|BFalse, s_A.get())).has_value());
2696 EXPECT_FALSE(
2698 make_specialized_arrmap(
2699 BDict,
2700 {map_elem(s_A, ival(1)), map_elem(s_B, ival(2))},
2701 TBottom, TBottom,
2702 LegacyMark::Unmarked
2704 ).has_value()
2706 EXPECT_FALSE(
2708 make_specialized_arrmap(
2709 BDictN,
2710 {map_elem_counted(s_A, ival(1)), map_elem_counted(s_B, ival(2))},
2711 TBottom, TBottom,
2712 LegacyMark::Unmarked
2714 ).has_value()
2717 EXPECT_FALSE(tv(sval_counted(s_A)).has_value());
2718 EXPECT_FALSE(tv(TCDictE).has_value());
2719 EXPECT_FALSE(tv(TCVecE).has_value());
2720 EXPECT_FALSE(tv(make_specialized_arrpacked(BVecN, {sval_counted(s_A)})).has_value());
2721 EXPECT_FALSE(tv(make_specialized_arrpacked(BCVec, {ival(123)})).has_value());
2722 EXPECT_FALSE(
2724 make_specialized_arrmap(
2725 BCDictN,
2726 {map_elem(s_A, ival(1)), map_elem(s_B, ival(2))},
2727 TBottom, TBottom,
2728 LegacyMark::Unmarked
2730 ).has_value()
2733 for (auto const& t : all) {
2734 EXPECT_EQ(is_scalar_counted(t), tvCounted(t).has_value());
2735 if (!t.hasData() && !t.subtypeOf(BNull | BBool | BArrLikeE)) {
2736 EXPECT_FALSE(tvCounted(t).has_value());
2739 if (is_scalar(t)) {
2740 EXPECT_TRUE(is_scalar_counted(t));
2741 EXPECT_TRUE(tvCounted(t).has_value());
2743 if (!is_scalar_counted(t)) {
2744 EXPECT_FALSE(is_scalar(t));
2745 EXPECT_FALSE(tv(t).has_value());
2748 if (!(t.couldBe(BStr) && t.subtypeAmong(BCStr, BStr)) &&
2749 !(t.couldBe(BVec) && t.subtypeAmong(BCVec, BVec)) &&
2750 !(t.couldBe(BDict) && t.subtypeAmong(BCDict, BDict)) &&
2751 !(t.couldBe(BKeyset) && t.subtypeAmong(BCKeyset, BKeyset))) {
2752 EXPECT_EQ(is_scalar(t), is_scalar_counted(t));
2753 EXPECT_EQ(tv(t).has_value(), tvCounted(t).has_value());
2756 if (t.couldBe(BInitNull) && !t.subtypeOf(BInitNull)) {
2757 EXPECT_FALSE(tvCounted(t).has_value());
2760 if (!t.subtypeOf(BInitNull)) {
2761 EXPECT_FALSE(is_scalar_counted(opt(t)));
2762 EXPECT_FALSE(tvCounted(opt(t)).has_value());
2765 if (t.couldBe(BArrLikeE)) {
2766 if (!t.subtypeAmong(BVecE, BArrLike) &&
2767 !t.subtypeAmong(BDictE, BArrLike) &&
2768 !t.subtypeAmong(BKeysetE, BArrLike)) {
2769 EXPECT_FALSE(tv(t).has_value());
2774 auto const testC = [&] (const Type& t, TypedValue d) {
2775 auto const val = tvCounted(t);
2776 EXPECT_TRUE(val && tvSame(*val, d));
2778 testC(make_unmarked(TCVecE), make_array_like_tv(staticEmptyVec()));
2779 testC(make_unmarked(TCDictE), make_array_like_tv(staticEmptyDictArray()));
2780 testC(TCKeysetE, make_array_like_tv(staticEmptyKeysetArray()));
2781 testC(sval_counted(s_A), tv(s_A));
2782 testC(
2783 make_unmarked(make_specialized_arrpacked(BVecN, {sval_counted(s_A)})),
2784 make_array_like_tv(const_cast<ArrayData*>(static_vec(s_A.get())))
2786 testC(
2787 make_unmarked(make_specialized_arrpacked(BCVecN, {sval(s_A)})),
2788 make_array_like_tv(const_cast<ArrayData*>(static_vec(s_A.get())))
2790 testC(
2791 make_specialized_arrmap(
2792 BDictN,
2793 {map_elem_counted(s_A, ival(1)), map_elem_counted(s_B, ival(2))},
2794 TBottom, TBottom,
2795 LegacyMark::Unmarked
2797 make_array_like_tv(const_cast<ArrayData*>(static_dict(s_A.get(), 1, s_B.get(), 2)))
2799 testC(
2800 make_specialized_arrmap(
2801 BCDictN,
2802 {map_elem(s_A, ival(1)), map_elem(s_B, ival(2))},
2803 TBottom, TBottom,
2804 LegacyMark::Unmarked
2806 make_array_like_tv(const_cast<ArrayData*>(static_dict(s_A.get(), 1, s_B.get(), 2)))
2810 TEST(Type, OptCouldBe) {
2811 for (auto const& t : optionals()) {
2812 if (t.subtypeOf(BInitNull)) continue;
2813 EXPECT_TRUE(t.couldBe(unopt(t)));
2816 const std::initializer_list<std::pair<Type, Type>> true_cases{
2817 { opt(sval(s_test)), TStr },
2818 { opt(sval(s_test)), TInitNull },
2819 { opt(sval(s_test)), TSStr },
2820 { opt(sval(s_test)), sval(s_test) },
2821 { opt(sval(s_test)), sval_nonstatic(s_test) },
2823 { opt(sval_nonstatic(s_test)), TStr },
2824 { opt(sval_nonstatic(s_test)), TInitNull },
2825 { opt(sval_nonstatic(s_test)), TSStr },
2826 { opt(sval_nonstatic(s_test)), sval_nonstatic(s_test) },
2827 { opt(sval_nonstatic(s_test)), sval(s_test) },
2829 { opt(lazyclsval(s_test)), TLazyCls },
2830 { opt(lazyclsval(s_test)), TInitNull },
2831 { opt(lazyclsval(s_test)), lazyclsval(s_test) },
2832 { opt(sval(s_test)), sval_nonstatic(s_test) },
2834 { opt(ival(2)), TInt },
2835 { opt(ival(2)), TInitNull },
2836 { opt(ival(2)), ival(2) },
2838 { opt(dval(2.0)), TDbl },
2839 { opt(dval(2.0)), TInitNull },
2840 { opt(dval(2.0)), dval(2) },
2842 { opt(TFalse), TBool },
2843 { opt(TFalse), TFalse },
2845 { opt(TTrue), TBool },
2846 { opt(TTrue), TTrue },
2848 { opt(TDbl), opt(TNum) },
2849 { TDbl, opt(TNum) },
2850 { TNum, opt(TDbl) },
2852 { opt(TInt), TNum },
2853 { TInt, opt(TNum) },
2854 { opt(TDbl), TNum },
2857 for (auto kv : true_cases) {
2858 EXPECT_TRUE(kv.first.couldBe(kv.second))
2859 << show(kv.first) << " couldBe " << show(kv.second)
2860 << " should be true";
2863 const std::initializer_list<std::pair<Type, Type>> false_cases{
2864 { opt(ival(2)), TDbl },
2865 { opt(dval(2.0)), TInt },
2866 { opt(TFalse), TTrue },
2867 { opt(TTrue), TFalse },
2868 { TFalse, opt(TNum) },
2871 for (auto kv : false_cases) {
2872 EXPECT_TRUE(!kv.first.couldBe(kv.second))
2873 << show(kv.first) << " couldBe " << show(kv.second)
2874 << " should be false";
2877 for (auto kv : boost::join(true_cases, false_cases)) {
2878 EXPECT_EQ(kv.first.couldBe(kv.second), kv.second.couldBe(kv.first))
2879 << show(kv.first) << " couldBe " << show(kv.second)
2880 << " wasn't reflexive";
2883 for (auto const& x : optionals()) {
2884 if (!x.subtypeOf(BInitNull)) {
2885 EXPECT_TRUE(x.couldBe(unopt(x)));
2887 EXPECT_TRUE(x.couldBe(BInitNull));
2888 for (auto const& y : optionals()) {
2889 EXPECT_TRUE(x.couldBe(y));
2894 TEST(Type, ArrayLikeElem) {
2895 auto const program = make_test_program();
2896 Index index { program.get() };
2898 const std::vector<Type> keys{
2899 TInt,
2900 TStr,
2901 TSStr,
2902 TCStr,
2903 TArrKey,
2904 TUncArrKey,
2905 sval(s_A),
2906 sval(s_B),
2907 sval(s_C),
2908 sval_nonstatic(s_A),
2909 sval_counted(s_A),
2910 ival(0),
2911 ival(1),
2912 ival(123),
2913 ival(777),
2914 ival(-1),
2915 ival(std::numeric_limits<int64_t>::max()),
2916 union_of(sval(s_A),TInt),
2917 union_of(sval(s_B),TInt),
2918 union_of(sval(s_C),TInt),
2919 union_of(sval_counted(s_A),TInt),
2920 union_of(ival(0),TStr),
2921 union_of(ival(1),TStr),
2922 union_of(ival(123),TStr),
2923 union_of(ival(777),TStr),
2924 union_of(ival(-1),TStr),
2925 union_of(ival(std::numeric_limits<int64_t>::max()),TStr)
2928 auto const& all = allCases(index);
2929 for (auto const& t : all) {
2930 if (!t.couldBe(BArrLike)) continue;
2932 EXPECT_EQ(array_like_elem(t, TStr), array_like_elem(t, TSStr));
2933 EXPECT_EQ(array_like_elem(t, TStr), array_like_elem(t, TCStr));
2934 EXPECT_EQ(array_like_elem(t, TArrKey), array_like_elem(t, TUncArrKey));
2935 EXPECT_EQ(array_like_elem(t, TArrKey), array_like_elem(t, Type{BInt|BCStr}));
2936 EXPECT_EQ(array_like_elem(t, sval(s_A)), array_like_elem(t, sval_nonstatic(s_A)));
2937 EXPECT_EQ(array_like_elem(t, sval(s_A)), array_like_elem(t, sval_counted(s_A)));
2938 EXPECT_EQ(array_like_elem(t, union_of(TInt,sval(s_A))),
2939 array_like_elem(t, union_of(TInt,sval_nonstatic(s_A))));
2940 EXPECT_EQ(array_like_elem(t, union_of(TInt,sval(s_A))),
2941 array_like_elem(t, union_of(TInt,sval_counted(s_A))));
2943 for (auto const& key : keys) {
2944 auto const elem = array_like_elem(t, key);
2946 if (elem.first.is(BBottom)) {
2947 EXPECT_FALSE(elem.second);
2949 if (t.couldBe(BArrLikeE)) {
2950 EXPECT_FALSE(elem.second);
2952 if (!is_specialized_array_like(t)) {
2953 EXPECT_FALSE(elem.second);
2954 if (!t.couldBe(BKeysetN)) {
2955 EXPECT_FALSE(elem.first.hasData());
2958 if (!key.hasData()) {
2959 EXPECT_FALSE(elem.second);
2961 if (elem.second) {
2962 EXPECT_TRUE(is_scalar_counted(key));
2963 EXPECT_TRUE(is_specialized_array_like_arrval(t) ||
2964 is_specialized_array_like_map(t) ||
2965 (key.subtypeOf(BInt) &&
2966 is_specialized_int(key) &&
2967 is_specialized_array_like_packed(t)));
2970 EXPECT_TRUE(elem.first.subtypeOf(BInitCell));
2971 if (!t.couldBe(BArrLikeN)) {
2972 EXPECT_TRUE(elem.first.is(BBottom));
2974 if (t.subtypeAmong(BSArrLikeN, BArrLikeN)) {
2975 EXPECT_TRUE(elem.first.subtypeOf(BInitUnc));
2977 if (t.subtypeAmong(BKeysetN, BArrLikeN)) {
2978 EXPECT_TRUE(elem.first.subtypeOf(BArrKey));
2980 if (t.subtypeAmong(BSKeysetN, BArrLikeN)) {
2981 EXPECT_TRUE(elem.first.subtypeOf(BUncArrKey));
2983 if (t.subtypeAmong(BKeysetN, BArrLikeN)) {
2984 EXPECT_TRUE(elem.first.subtypeOf(loosen_staticness(key)));
2987 if (t.subtypeAmong(BVecN, BArrLikeN) && !key.couldBe(BInt)) {
2988 EXPECT_TRUE(elem.first.is(BBottom));
2990 if ((is_specialized_array_like_packedn(t) ||
2991 is_specialized_array_like_packed(t)) && !key.couldBe(BInt)) {
2992 EXPECT_TRUE(elem.first.is(BBottom));
2994 if ((is_specialized_array_like_packedn(t) ||
2995 is_specialized_array_like_packed(t)) &&
2996 is_specialized_int(key) && ival_of(key) < 0) {
2997 EXPECT_TRUE(elem.first.is(BBottom));
3000 if (t.subtypeOf(BCell)) {
3001 auto const arr = split_array_like(t).first;
3002 EXPECT_EQ(array_like_elem(arr, key), elem);
3005 auto const unionTest = [&] (const Type& key2) {
3006 auto const elem2 = array_like_elem(t, key2);
3007 auto const elem3 = array_like_elem(t, union_of(key, key2));
3008 EXPECT_EQ(elem3.first, union_of(elem.first, elem2.first));
3009 EXPECT_EQ(elem3.second, elem.second && elem2.second);
3011 if (!key.hasData() || is_specialized_int(key)) unionTest(TInt);
3012 if (!key.hasData() || is_specialized_string(key)) unionTest(TStr);
3013 if (!key.hasData()) unionTest(TArrKey);
3017 auto const staticVec = static_vec(s_A, 100, s_B);
3018 auto const staticDict = static_dict(s_A, 100, 200, s_B, s_C, s_BA);
3019 auto const staticKeyset = static_keyset(s_A, 100, s_B);
3021 auto const mapElems1 = MapElems{
3022 map_elem(s_A, ival(100)),
3023 map_elem(200, sval(s_B)),
3024 map_elem(s_C, sval(s_BA))
3026 auto const mapElems2 = MapElems{
3027 map_elem_nonstatic(s_A, ival(100)),
3028 map_elem(200, sval(s_B)),
3029 map_elem_nonstatic(s_C, sval(s_BA))
3031 auto const mapElems3 = MapElems{
3032 map_elem(s_A, TObj),
3033 map_elem(s_B, TArrKey)
3035 auto const mapElems4 = MapElems{
3036 map_elem(100, TObj),
3037 map_elem(200, TFalse)
3040 const std::vector<std::tuple<Type, Type, Type, bool>> tests{
3041 { TVecE, TInt, TBottom, false },
3042 { TVecE, TStr, TBottom, false },
3043 { TVecE, TArrKey, TBottom, false },
3044 { TVecN, TInt, TInitCell, false },
3045 { TVec, TInt, TInitCell, false },
3046 { TSVecN, TInt, TInitUnc, false },
3047 { TVecN, TStr, TBottom, false },
3048 { TVecN, ival(-1), TBottom, false },
3049 { TVecN, ival(0), TInitCell, false },
3050 { TSVecN, ival(0), TInitUnc, false },
3051 { TVecN, TArrKey, TInitCell, false },
3052 { TSVecN, TArrKey, TInitUnc, false },
3053 { TVecN, union_of(ival(-1),TStr), TInitCell, false },
3054 { TVecN, union_of(ival(0),TStr), TInitCell, false },
3055 { TVecN, union_of(TInt,sval(s_A)), TInitCell, false },
3057 { TDictE, TInt, TBottom, false },
3058 { TDictE, TStr, TBottom, false },
3059 { TDictE, TArrKey, TBottom, false },
3060 { TDictN, TInt, TInitCell, false },
3061 { TDict, TInt, TInitCell, false },
3062 { TDict, TStr, TInitCell, false },
3063 { TSDictN, TInt, TInitUnc, false },
3064 { TDictN, TStr, TInitCell, false },
3065 { TSDictN, TStr, TInitUnc, false },
3066 { TDictN, ival(-1), TInitCell, false },
3067 { TSDictN, ival(-1), TInitUnc, false },
3068 { TDictN, ival(0), TInitCell, false },
3069 { TSDictN, ival(0), TInitUnc, false },
3070 { TDictN, sval(s_A), TInitCell, false },
3071 { TSDictN, sval(s_A), TInitUnc, false },
3072 { TDictN, union_of(ival(-1),TStr), TInitCell, false },
3073 { TDictN, union_of(ival(0),TStr), TInitCell, false },
3074 { TDictN, union_of(TInt,sval(s_A)), TInitCell, false },
3075 { TDictN, TArrKey, TInitCell, false },
3076 { TSDictN, TArrKey, TInitUnc, false },
3078 { TKeysetE, TInt, TBottom, false },
3079 { TKeysetE, TStr, TBottom, false },
3080 { TKeysetE, TArrKey, TBottom, false },
3081 { TKeysetN, TInt, TInt, false },
3082 { TKeyset, TStr, TStr, false },
3083 { TKeyset, TSStr, TStr, false },
3084 { TKeyset, TCStr, TStr, false },
3085 { TKeyset, TInt, TInt, false },
3086 { TKeyset, TArrKey, TArrKey, false },
3087 { TKeyset, TUncArrKey, TArrKey, false },
3088 { TSKeyset, TArrKey, TUncArrKey, false },
3089 { TSKeyset, TStr, TSStr, false },
3090 { TSKeyset, TInt, TInt, false },
3091 { TKeysetN, ival(-1), ival(-1), false },
3092 { TSKeysetN, ival(-1), ival(-1), false },
3093 { TKeysetN, ival(0), ival(0), false },
3094 { TSKeysetN, ival(0), ival(0), false },
3095 { TKeysetN, sval(s_A), sval_nonstatic(s_A), false },
3096 { TSKeysetN, sval(s_A), sval(s_A), false },
3097 { TKeysetN, sval_nonstatic(s_A), sval_nonstatic(s_A), false },
3098 { TSKeysetN, sval_nonstatic(s_A), sval(s_A), false },
3099 { TKeysetN, union_of(ival(0),TStr), union_of(ival(0),TStr), false },
3100 { TSKeysetN, union_of(ival(0),TStr), union_of(ival(0),TSStr), false },
3101 { TKeysetN, union_of(TInt,sval(s_A)), union_of(TInt,sval_nonstatic(s_A)), false },
3102 { TSKeysetN, union_of(TInt,sval(s_A)), union_of(TInt,sval(s_A)), false },
3104 { make_specialized_arrval(BSVecN, staticVec), TInt, TUncArrKey, false },
3105 { make_specialized_arrval(BSVecN, staticVec), TStr, TBottom, false },
3106 { make_specialized_arrval(BSVecN, staticVec), TArrKey, TUncArrKey, false },
3107 { make_specialized_arrval(BSVecN, staticVec), ival(0), sval(s_A), true },
3108 { make_specialized_arrval(BSVec, staticVec), ival(0), sval(s_A), false },
3109 { make_specialized_arrval(BSVecN, staticVec), ival(1), ival(100), true },
3110 { make_specialized_arrval(BSVec, staticVec), ival(1), ival(100), false },
3111 { make_specialized_arrval(BSVecN, staticVec), ival(3), TBottom, false },
3112 { make_specialized_arrval(BSVecN, staticVec), ival(-1), TBottom, false },
3113 { make_specialized_arrval(BSVecN, staticVec), sval(s_A), TBottom, false },
3114 { make_specialized_arrval(BSVecN, staticVec), union_of(ival(0),TStr), TUncArrKey, false },
3115 { make_specialized_arrval(BSVecN, staticVec), union_of(ival(1),TStr), TUncArrKey, false },
3116 { make_specialized_arrval(BSVecN, staticVec), union_of(TInt,sval(s_A)), TUncArrKey, false },
3118 { make_specialized_arrval(BSDictN, staticDict), TInt, sval(s_B), false },
3119 { make_specialized_arrval(BSDictN, staticDict), TStr, union_of(sval(s_BA),TInt), false },
3120 { make_specialized_arrval(BSDictN, staticDict), TCStr, union_of(sval(s_BA),TInt), false },
3121 { make_specialized_arrval(BSDictN, staticDict), TArrKey, TUncArrKey, false },
3122 { make_specialized_arrval(BSDictN, staticDict), ival(0), TBottom, false },
3123 { make_specialized_arrval(BSDictN, staticDict), ival(-1), TBottom, false },
3124 { make_specialized_arrval(BSDictN, staticDict), ival(200), sval(s_B), true },
3125 { make_specialized_arrval(BSDict, staticDict), ival(200), sval(s_B), false },
3126 { make_specialized_arrval(BSDictN, staticDict), sval(s_A), ival(100), true },
3127 { make_specialized_arrval(BSDict, staticDict), sval(s_A), ival(100), false },
3128 { make_specialized_arrval(BSDictN, staticDict), sval_counted(s_A), ival(100), true },
3129 { make_specialized_arrval(BSDictN, staticDict), sval(s_C), sval(s_BA), true },
3130 { make_specialized_arrval(BSDict, staticDict), sval(s_C), sval(s_BA), false },
3131 { make_specialized_arrval(BSDictN, staticDict), sval_counted(s_C), sval(s_BA), true },
3132 { make_specialized_arrval(BSDictN, staticDict), union_of(ival(0),TStr), union_of(TInt,sval(s_BA)), false },
3133 { make_specialized_arrval(BSDictN, staticDict), union_of(ival(100),TStr), union_of(TInt,sval(s_BA)), false },
3134 { make_specialized_arrval(BSDictN, staticDict), union_of(TInt,sval(s_A)), union_of(TInt,sval(s_B)), false },
3135 { make_specialized_arrval(BSDictN, staticDict), union_of(TInt,sval(s_C)), TUncArrKey, false },
3137 { make_specialized_arrval(BSKeysetN, staticKeyset), TInt, ival(100), false },
3138 { make_specialized_arrval(BSKeysetN, staticKeyset), TStr, TSStr, false },
3139 { make_specialized_arrval(BSKeysetN, staticKeyset), TArrKey, TUncArrKey, false },
3140 { make_specialized_arrval(BSKeysetN, staticKeyset), ival(0), TBottom, false },
3141 { make_specialized_arrval(BSKeysetN, staticKeyset), sval(s_C), TBottom, false },
3142 { make_specialized_arrval(BSKeysetN, staticKeyset), ival(100), ival(100), true },
3143 { make_specialized_arrval(BSKeyset, staticKeyset), ival(100), ival(100), false },
3144 { make_specialized_arrval(BSKeysetN, staticKeyset), sval(s_A), sval(s_A), true },
3145 { make_specialized_arrval(BSKeyset, staticKeyset), sval(s_A), sval(s_A), false },
3146 { make_specialized_arrval(BSKeysetN, staticKeyset), sval_counted(s_A), sval(s_A), true },
3147 { make_specialized_arrval(BSKeysetN, staticKeyset), sval(s_B), sval(s_B), true },
3148 { make_specialized_arrval(BSKeyset, staticKeyset), sval(s_B), sval(s_B), false },
3149 { make_specialized_arrval(BSKeysetN, staticKeyset), sval_counted(s_B), sval(s_B), true },
3150 { make_specialized_arrval(BSKeysetN, staticKeyset), union_of(ival(0),TStr), TUncArrKey, false },
3151 { make_specialized_arrval(BSKeysetN, staticKeyset), union_of(ival(100),TStr), union_of(ival(100),TSStr), false },
3152 { make_specialized_arrval(BSKeysetN, staticKeyset), union_of(TInt,sval(s_A)), union_of(TInt,sval(s_A)), false },
3153 { make_specialized_arrval(BSKeysetN, staticKeyset), union_of(TInt,sval(s_B)), union_of(TInt,sval(s_B)), false },
3155 { make_specialized_arrpackedn(BDictN, TInitCell), TInt, TInitCell, false },
3156 { make_specialized_arrpackedn(BDictN, TInitCell), TStr, TBottom, false },
3157 { make_specialized_arrpackedn(BDictN, TInitCell), TArrKey, TInitCell, false },
3158 { make_specialized_arrpackedn(BDictN, TInitCell), ival(-1), TBottom, false },
3159 { make_specialized_arrpackedn(BDictN, TInitCell), sval(s_A), TBottom, false },
3160 { make_specialized_arrpackedn(BDictN, TInitCell), ival(0), TInitCell, false },
3161 { make_specialized_arrpackedn(BSDictN, TInitUnc), ival(0), TInitUnc, false },
3162 { make_specialized_arrpackedn(BDictN, TObj), ival(0), TObj, false },
3163 { make_specialized_arrpackedn(BDict, TObj), ival(0), TObj, false },
3164 { make_specialized_arrpackedn(BDictN, TSStr), ival(0), TSStr, false },
3165 { make_specialized_arrpackedn(BDictN, TObj), union_of(ival(-1),TStr), TObj, false },
3166 { make_specialized_arrpackedn(BDictN, TObj), union_of(ival(0),TStr), TObj, false },
3167 { make_specialized_arrpackedn(BDictN, TObj), union_of(TInt,sval(s_A)), TObj, false },
3169 { make_specialized_arrpacked(BDictN, {TInitCell}), TInt, TInitCell, false },
3170 { make_specialized_arrpacked(BDictN, {TInitCell}), TStr, TBottom, false },
3171 { make_specialized_arrpacked(BDictN, {TInitCell}), TArrKey, TInitCell, false },
3172 { make_specialized_arrpacked(BDictN, {TInitCell}), ival(-1), TBottom, false },
3173 { make_specialized_arrpacked(BDictN, {TInitCell}), sval(s_A), TBottom, false },
3174 { make_specialized_arrpacked(BDictN, {TInitCell}), ival(1), TBottom, false },
3175 { make_specialized_arrpacked(BDictN, {TInitCell}), ival(0), TInitCell, true },
3176 { make_specialized_arrpacked(BDict, {TInitCell}), ival(0), TInitCell, false },
3177 { make_specialized_arrpacked(BSDictN, {TInitUnc}), ival(0), TInitUnc, true },
3178 { make_specialized_arrpacked(BSDict, {TInitUnc}), ival(0), TInitUnc, false },
3179 { make_specialized_arrpacked(BDictN, {TObj}), ival(0), TObj, true },
3180 { make_specialized_arrpacked(BDictN, {TSStr}), TInt, TSStr, false },
3181 { make_specialized_arrpacked(BDictN, {TObj}), union_of(ival(1),TStr), TObj, false },
3182 { make_specialized_arrpacked(BDictN, {TObj}), union_of(ival(0),TStr), TObj, false },
3183 { make_specialized_arrpacked(BDictN, {TObj}), union_of(TInt,sval(s_A)), TObj, false },
3184 { make_specialized_arrpacked(BDictN, {TObj, TInt}), TInt, Type{BObj|BInt}, false },
3185 { make_specialized_arrpacked(BDictN, {TObj, TInt}), ival(0), TObj, true },
3186 { make_specialized_arrpacked(BDictN, {TObj, TInt}), ival(1), TInt, true },
3187 { make_specialized_arrpacked(BDictN, {TObj, TInt}), ival(2), TBottom, false },
3189 { make_specialized_arrmapn(BDictN, TArrKey, TObj), TInt, TObj, false },
3190 { make_specialized_arrmapn(BDictN, TArrKey, TObj), TStr, TObj, false },
3191 { make_specialized_arrmapn(BDictN, TArrKey, TObj), TSStr, TObj, false },
3192 { make_specialized_arrmapn(BDictN, TArrKey, TObj), TCStr, TObj, false },
3193 { make_specialized_arrmapn(BDictN, TArrKey, TObj), TArrKey, TObj, false },
3194 { make_specialized_arrmapn(BDictN, TArrKey, TObj), TUncArrKey, TObj, false },
3195 { make_specialized_arrmapn(BDictN, TArrKey, TObj), ival(0), TObj, false },
3196 { make_specialized_arrmapn(BDictN, TArrKey, TObj), ival(-1), TObj, false },
3197 { make_specialized_arrmapn(BDictN, TArrKey, TObj), sval(s_A), TObj, false },
3198 { make_specialized_arrmapn(BDictN, TUncArrKey, TObj), TInt, TObj, false },
3199 { make_specialized_arrmapn(BDictN, TUncArrKey, TObj), TStr, TObj, false },
3200 { make_specialized_arrmapn(BDictN, TUncArrKey, TObj), TSStr, TObj, false },
3201 { make_specialized_arrmapn(BDictN, TUncArrKey, TObj), TCStr, TObj, false },
3202 { make_specialized_arrmapn(BDictN, TUncArrKey, TObj), TArrKey, TObj, false },
3203 { make_specialized_arrmapn(BDictN, TUncArrKey, TObj), TUncArrKey, TObj, false },
3204 { make_specialized_arrmapn(BDictN, TUncArrKey, TSStr), TInt, TSStr, false },
3205 { make_specialized_arrmapn(BDictN, TInt, TObj), TInt, TObj, false },
3206 { make_specialized_arrmapn(BDictN, TInt, TObj), TStr, TBottom, false },
3207 { make_specialized_arrmapn(BDictN, TInt, TObj), TArrKey, TObj, false },
3209 { make_specialized_arrmap(BDictN, mapElems1), TInt, sval(s_B), false },
3210 { make_specialized_arrmap(BDictN, mapElems1), TStr, union_of(TInt,sval(s_BA)), false },
3211 { make_specialized_arrmap(BDictN, mapElems1), TSStr, union_of(TInt,sval(s_BA)), false },
3212 { make_specialized_arrmap(BDictN, mapElems1), TCStr, union_of(TInt,sval(s_BA)), false },
3213 { make_specialized_arrmap(BDictN, mapElems2), TInt, sval(s_B), false },
3214 { make_specialized_arrmap(BDictN, mapElems2), TStr, union_of(TInt,sval(s_BA)), false },
3215 { make_specialized_arrmap(BDictN, mapElems2), TSStr, union_of(TInt,sval(s_BA)), false },
3216 { make_specialized_arrmap(BDictN, mapElems2), TCStr, union_of(TInt,sval(s_BA)), false },
3217 { make_specialized_arrmap(BDictN, mapElems1), TArrKey, TUncArrKey, false },
3218 { make_specialized_arrmap(BDictN, mapElems1), TUncArrKey, TUncArrKey, false },
3219 { make_specialized_arrmap(BDictN, mapElems2), TArrKey, TUncArrKey, false },
3220 { make_specialized_arrmap(BDictN, mapElems2), TUncArrKey, TUncArrKey, false },
3221 { make_specialized_arrmap(BDictN, mapElems3), TInt, TBottom, false },
3222 { make_specialized_arrmap(BDictN, mapElems3), TStr, Type{BObj|BArrKey}, false },
3223 { make_specialized_arrmap(BDictN, mapElems3), ival(100), TBottom, false },
3224 { make_specialized_arrmap(BDictN, mapElems1), ival(0), TBottom, false },
3225 { make_specialized_arrmap(BDictN, mapElems1), sval(s_B), TBottom, false },
3226 { make_specialized_arrmap(BDictN, mapElems1), ival(200), sval(s_B), true },
3227 { make_specialized_arrmap(BDict, mapElems1), ival(200), sval(s_B), false },
3228 { make_specialized_arrmap(BDictN, mapElems1), sval(s_A), ival(100), true },
3229 { make_specialized_arrmap(BDict, mapElems1), sval(s_A), ival(100), false },
3230 { make_specialized_arrmap(BDictN, mapElems1), sval_nonstatic(s_A), ival(100), true },
3231 { make_specialized_arrmap(BDictN, mapElems1), sval_counted(s_A), ival(100), true },
3232 { make_specialized_arrmap(BDictN, mapElems2), ival(200), sval(s_B), true },
3233 { make_specialized_arrmap(BDictN, mapElems2), sval(s_A), ival(100), true },
3234 { make_specialized_arrmap(BDictN, mapElems2), sval_nonstatic(s_A), ival(100), true },
3235 { make_specialized_arrmap(BDictN, mapElems2), sval_counted(s_A), ival(100), true },
3236 { make_specialized_arrmap(BDictN, mapElems3), union_of(ival(0),TStr), Type{BObj|BArrKey}, false },
3237 { make_specialized_arrmap(BDictN, mapElems3), union_of(TInt,sval(s_BA)), Type{BArrKey|BObj}, false },
3238 { make_specialized_arrmap(BDictN, mapElems3), union_of(TInt,sval(s_A)), Type{BArrKey|BObj}, false },
3239 { make_specialized_arrmap(BDictN, mapElems3), union_of(TInt,sval(s_B)), Type{BArrKey|BObj}, false },
3240 { make_specialized_arrmap(BDictN, mapElems1), union_of(ival(0),TStr), union_of(TInt,sval(s_BA)), false },
3241 { make_specialized_arrmap(BDictN, mapElems1), union_of(TInt,sval(s_BA)), TUncArrKey, false },
3242 { make_specialized_arrmap(BDictN, mapElems1), union_of(TInt,sval(s_A)), union_of(TInt,sval(s_B)), false },
3243 { make_specialized_arrmap(BDictN, mapElems1), union_of(ival(200),TStr), TUncArrKey, false },
3244 { make_specialized_arrmap(BDictN, mapElems4), union_of(ival(100),TStr), Type{BObj|BFalse}, false },
3245 { make_specialized_arrmap(BDictN, mapElems4), union_of(ival(200),TStr), Type{BObj|BFalse}, false },
3246 { make_specialized_arrmap(BDictN, mapElems1, TInt, TObj), ival(0), TObj, false },
3247 { make_specialized_arrmap(BDictN, mapElems1, TSStr, TObj), sval(s_BA), TObj, false },
3248 { make_specialized_arrmap(BDictN, mapElems1, TSStr, TObj), sval_nonstatic(s_BA), TObj, false },
3249 { make_specialized_arrmap(BDictN, mapElems1, TSStr, TObj), sval_counted(s_BA), TObj, false },
3250 { make_specialized_arrmap(BDictN, mapElems1, TSStr, TObj), ival(0), TBottom, false },
3251 { make_specialized_arrmap(BDictN, mapElems1, TInt, TObj), sval(s_A), ival(100), true },
3252 { make_specialized_arrmap(BDictN, mapElems1, TStr, TObj), sval(s_A), ival(100), true },
3253 { make_specialized_arrmap(BDictN, mapElems3, TInt, TFalse), TInt, TFalse, false },
3254 { make_specialized_arrmap(BDictN, mapElems3, TInt, TFalse), ival(0), TFalse, false },
3255 { make_specialized_arrmap(BDictN, mapElems3, TStr, TFalse), TInt, TBottom, false },
3256 { make_specialized_arrmap(BDictN, mapElems4, TSStr, TNum), TStr, TNum, false },
3257 { make_specialized_arrmap(BDictN, mapElems4, TSStr, TNum), TCStr, TNum, false },
3258 { make_specialized_arrmap(BDictN, mapElems4, TSStr, TNum), TSStr, TNum, false },
3259 { make_specialized_arrmap(BDictN, mapElems4, TSStr, TNum), sval(s_A), TNum, false },
3260 { make_specialized_arrmap(BDictN, mapElems4, TSStr, TNum), sval_nonstatic(s_A), TNum, false },
3261 { make_specialized_arrmap(BDictN, mapElems4, TSStr, TNum), sval_counted(s_A), TNum, false },
3262 { make_specialized_arrmap(BDictN, mapElems4, TStr, TNum), union_of(ival(0),TStr), Type{BNum|BFalse|BObj}, false },
3263 { make_specialized_arrmap(BDictN, mapElems4, TStr, TNum), union_of(ival(100),TStr), Type{BObj|BNum|BFalse}, false },
3264 { make_specialized_arrmap(BDictN, mapElems3, TInt, TNum), union_of(TInt,sval(s_BA)), Type{BObj|BNum|BStr}, false },
3265 { make_specialized_arrmap(BDictN, mapElems3, TInt, TNum), union_of(TInt,sval(s_A)), Type{BObj|BNum|BStr}, false }
3267 for (auto const& t : tests) {
3268 auto const elem = array_like_elem(std::get<0>(t), std::get<1>(t));
3269 EXPECT_EQ(elem.first, std::get<2>(t));
3270 EXPECT_EQ(elem.second, std::get<3>(t));
3274 TEST(Type, ArrayLikeNewElem) {
3275 auto const program = make_test_program();
3276 Index index { program.get() };
3278 const std::vector<Type> values{
3279 TInt,
3280 TStr,
3281 TSStr,
3282 TCStr,
3283 TUncArrKey,
3284 TArrKey,
3285 ival(0),
3286 ival(1),
3287 ival(123),
3288 ival(777),
3289 ival(-1),
3290 ival(std::numeric_limits<int64_t>::max()),
3291 sval(s_A),
3292 sval(s_B),
3293 sval(s_C),
3294 sval_nonstatic(s_A),
3295 sval_counted(s_A),
3296 TObj,
3297 TInitUnc,
3298 TInitCell,
3299 Type{BObj|BInt},
3300 union_of(sval(s_A),TInt),
3301 union_of(sval(s_B),TInt),
3302 union_of(sval(s_C),TInt),
3303 union_of(sval_counted(s_A),TInt),
3304 union_of(ival(0),TStr),
3305 union_of(ival(1),TStr),
3306 union_of(ival(123),TStr),
3307 union_of(ival(777),TStr),
3308 union_of(ival(-1),TStr),
3309 union_of(ival(std::numeric_limits<int64_t>::max()),TStr)
3312 auto const& all = allCases(index);
3313 for (auto const& t : all) {
3314 if (!t.subtypeOf(BCell) || !t.couldBe(BArrLike)) continue;
3316 for (auto const& v : values) {
3317 auto const newelem = array_like_newelem(t, v);
3318 EXPECT_FALSE(newelem.first.couldBe(BArrLikeE));
3320 if (!newelem.first.couldBe(BArrLike)) {
3321 EXPECT_TRUE(newelem.second);
3322 } else {
3323 EXPECT_FALSE(newelem.first.subtypeAmong(BSArrLike, BArrLike));
3324 if (!t.subtypeAmong(BKeyset, BArrLike) &&
3325 !array_like_elem(newelem.first, ival(std::numeric_limits<int64_t>::max())).second) {
3326 EXPECT_TRUE(v.subtypeOf(array_like_elem(newelem.first, TInt).first));
3330 if (t.subtypeAmong(BVec, BArrLike)) {
3331 EXPECT_FALSE(newelem.second);
3334 if (!t.couldBe(BArrLikeN) && !t.couldBe(BKeyset)) {
3335 EXPECT_TRUE(newelem.first.couldBe(BArrLike));
3336 EXPECT_TRUE(is_specialized_array_like_packed(newelem.first));
3337 EXPECT_EQ(array_like_elem(newelem.first, ival(0)).first, v);
3338 auto const size = arr_size(split_array_like(newelem.first).first);
3339 EXPECT_TRUE(size && *size == 1);
3340 EXPECT_EQ(array_like_elem(newelem.first, ival(1)).first, TBottom);
3341 EXPECT_FALSE(newelem.second);
3344 auto [arr, rest] = split_array_like(t);
3345 auto const elem2 = array_like_newelem(arr, v);
3346 EXPECT_EQ(newelem.first, union_of(elem2.first, rest));
3347 EXPECT_EQ(newelem.second, elem2.second);
3351 auto const mapElem1 = MapElems{
3352 map_elem(s_A, TInt),
3353 map_elem(s_B, TObj)
3355 auto const mapElem2 = MapElems{
3356 map_elem(s_A, TInt),
3357 map_elem(100, TObj),
3358 map_elem(s_B, TFalse),
3359 map_elem(50, TObj),
3361 auto const mapElem3 = MapElems{
3362 map_elem(std::numeric_limits<int64_t>::max(), TInitCell)
3364 auto const mapElem4 = MapElems{
3365 map_elem(s_A, TInt),
3366 map_elem(s_B, TObj),
3367 map_elem(int64_t(0), TFalse)
3369 auto const mapElem5 = MapElems{
3370 map_elem(s_A, TInt),
3371 map_elem(100, TObj),
3372 map_elem(s_B, TFalse),
3373 map_elem(50, TObj),
3374 map_elem(101, TInitCell)
3376 auto const mapElem6 = MapElems{
3377 map_elem(s_A, ival(100)),
3378 map_elem(200, sval(s_B)),
3379 map_elem(s_C, sval(s_BA)),
3380 map_elem(201, TInt)
3382 auto const mapElem7 = MapElems{
3383 map_elem(1, ival(1))
3385 auto const mapElem8 = MapElems{
3386 map_elem(s_A, sval(s_A))
3388 auto const mapElem9 = MapElems{
3389 map_elem(int64_t(0), ival(0)),
3390 map_elem(s_A, sval(s_A))
3392 auto const mapElem10 = MapElems{
3393 map_elem(int64_t(0), ival(0)),
3394 map_elem(1, ival(1)),
3395 map_elem(s_A, sval(s_A))
3397 auto const mapElem11 = MapElems{
3398 map_elem(int64_t(0), ival(0)),
3399 map_elem_nonstatic(s_A, sval_nonstatic(s_A))
3401 auto const mapElem12 = MapElems{
3402 map_elem(int64_t(0), ival(0)),
3403 map_elem(1, ival(1)),
3404 map_elem_nonstatic(s_A, sval_nonstatic(s_A))
3406 auto const mapElem13 = MapElems{
3407 map_elem(int64_t(0), ival(0)),
3408 map_elem(-1, ival(-1))
3410 auto const mapElem14 = MapElems{
3411 map_elem(int64_t(0), ival(0)),
3412 map_elem(1, ival(1)),
3413 map_elem(3, ival(3))
3415 auto const mapElem15 = MapElems{
3416 map_elem(int64_t(0), ival(0)),
3417 map_elem(1, ival(1)),
3418 map_elem(s_A, sval(s_A)),
3419 map_elem(100, ival(100))
3421 auto const mapElem16 = MapElems{
3422 map_elem(int64_t(0), ival(0)),
3423 map_elem(1, ival(1)),
3424 map_elem(s_A, sval(s_A)),
3425 map_elem_nonstatic(s_B, sval_nonstatic(s_B))
3427 auto const mapElem17 = MapElems{
3428 map_elem(int64_t(0), ival(0)),
3429 map_elem(1, ival(1)),
3430 map_elem(s_A, sval(s_A)),
3431 map_elem(s_B, sval(s_B))
3433 auto const mapElem18 = MapElems{
3434 map_elem(1, ival(1)),
3435 map_elem(s_A, sval(s_A))
3437 auto const mapElem19 = MapElems{
3438 map_elem_nonstatic(s_A, sval_nonstatic(s_A))
3441 auto const staticVec = static_vec(s_A, s_B, s_C);
3442 auto const staticDict = static_dict(s_A, 100, 200, s_B, s_C, s_BA);
3444 const std::vector<std::tuple<Type, Type, Type, bool>> tests{
3445 { TVecE, TObj, make_specialized_arrpacked(BVecN, {TObj}), false },
3446 { TSVecE, TObj, make_specialized_arrpacked(BVecN, {TObj}), false },
3447 { TCVecE, TObj, make_specialized_arrpacked(BVecN, {TObj}), false },
3448 { TVecN, TObj, TVecN, false },
3449 { TSVecN, TObj, TVecN, false },
3450 { TCVecN, TObj, TVecN, false },
3451 { TVec, TObj, TVecN, false },
3452 { TSVec, TObj, TVecN, false },
3453 { TCVec, TObj, TVecN, false },
3454 { TDictE, TObj, make_specialized_arrpacked(BDictN, {TObj}), false },
3455 { TSDictE, TObj, make_specialized_arrpacked(BDictN, {TObj}), false },
3456 { TCDictE, TObj, make_specialized_arrpacked(BDictN, {TObj}), false },
3457 { TDictN, TObj, TDictN, true },
3458 { TSDictN, TObj, TDictN, true },
3459 { TCDictN, TObj, TDictN, true },
3460 { TDict, TObj, TDictN, true },
3461 { TSDict, TObj, TDictN, true },
3462 { TCDict, TObj, TDictN, true },
3463 { TKeysetE, TObj, TBottom, true },
3464 { TKeysetN, TObj, TBottom, true },
3465 { TKeyset, TObj, TBottom, true },
3466 { TSKeysetE, TFalse, TBottom, true },
3467 { TSKeysetN, TFalse, TBottom, true },
3468 { TSKeyset, TFalse, TBottom, true },
3469 { TSKeysetE, TInt, make_specialized_arrmapn(BKeysetN, TInt, TInt), false },
3470 { TKeysetE, TInitCell, TKeysetN, true },
3471 { TKeysetE, TInitUnc, make_specialized_arrmapn(BKeysetN, TUncArrKey, TUncArrKey), true },
3472 { TKeysetE, ival(0), make_specialized_arrpacked(BKeysetN, {ival(0)}), false },
3473 { TSKeysetE, ival(1), make_specialized_arrmap(BKeysetN, mapElem7), false },
3474 { TKeysetE, sval(s_A), make_specialized_arrmap(BKeysetN, mapElem8), false },
3475 { TKeysetE, TCls, make_specialized_arrmapn(BKeysetN, TSStr, TSStr), true },
3476 { TKeysetE, TLazyCls, make_specialized_arrmapn(BKeysetN, TSStr, TSStr), true },
3477 { TKeysetN, TInt, TKeysetN, false },
3478 { TKeyset, TInt, TKeysetN, false },
3479 { TSKeysetN, TInt, TKeysetN, false },
3480 { TSKeyset, TInt, TKeysetN, false },
3481 { TCKeysetN, TInt, TKeysetN, false },
3482 { TCKeyset, TInt, TKeysetN, false },
3483 { TKeysetN, TLazyCls, TKeysetN, true },
3484 { TKeysetN, TCls, TKeysetN, true },
3486 { make_specialized_arrval(BSVecN, staticVec),
3487 TInt, make_specialized_arrpacked(BVecN, {sval(s_A), sval(s_B), sval(s_C), TInt}), false },
3488 { make_specialized_arrval(BSVec, staticVec), TInt, make_specialized_arrpackedn(BVecN, TUncArrKey), false },
3489 { make_specialized_arrval(BSDictN, staticDict), TInt, make_specialized_arrmap(BDictN, mapElem6), false },
3490 { make_specialized_arrval(BSDict, staticDict), TInt, make_specialized_arrmapn(BDictN, TUncArrKey, TUncArrKey), false },
3492 { make_specialized_arrpackedn(BVecN, TInt), TStr, make_specialized_arrpackedn(BVecN, TArrKey), false },
3493 { make_specialized_arrpackedn(BSVecN, TSStr), TInt, make_specialized_arrpackedn(BVecN, TUncArrKey), false },
3494 { make_specialized_arrpackedn(BVecN, Type{BInitCell & ~BObj}), TObj, TVecN, false },
3495 { make_specialized_arrpackedn(BVec, TInt), TStr, make_specialized_arrpackedn(BVecN, TArrKey), false },
3496 { make_specialized_arrpackedn(BSVec, TSStr), TInt, make_specialized_arrpackedn(BVecN, TUncArrKey), false },
3497 { make_specialized_arrpackedn(BVec, Type{BInitCell & ~BObj}), TObj, TVecN, false },
3498 { make_specialized_arrpackedn(BDictN, TInt), TStr, make_specialized_arrpackedn(BDictN, TArrKey), false },
3499 { make_specialized_arrpackedn(BSDictN, TSStr), TInt, make_specialized_arrpackedn(BDictN, TUncArrKey), false },
3500 { make_specialized_arrpackedn(BDictN, Type{BInitCell & ~BObj}), TObj, make_specialized_arrpackedn(BDictN, TInitCell), false },
3501 { make_specialized_arrpackedn(BDict, TInt), TStr, make_specialized_arrpackedn(BDictN, TArrKey), false },
3502 { make_specialized_arrpackedn(BSDict, TSStr), TInt, make_specialized_arrpackedn(BDictN, TUncArrKey), false },
3503 { make_specialized_arrpackedn(BDict, Type{BInitCell & ~BObj}), TObj, make_specialized_arrpackedn(BDictN, TInitCell), false },
3504 { make_specialized_arrpackedn(BKeyset, TInt), TInt, make_specialized_arrmapn(BKeysetN, TInt, TInt), false },
3505 { make_specialized_arrpackedn(BKeyset, TInt), TStr, TKeysetN, false },
3506 { make_specialized_arrpackedn(BKeyset, TInt), TSStr, make_specialized_arrmapn(BKeysetN, TUncArrKey, TUncArrKey), false },
3507 { make_specialized_arrpackedn(BKeyset, TInt), sval(s_A),
3508 make_specialized_arrmapn(BKeysetN, union_of(TInt,sval(s_A)), union_of(TInt,sval(s_A))), false },
3509 { make_specialized_arrpackedn(BKeyset, TInt), ival(0), make_specialized_arrpackedn(BKeysetN, TInt), false },
3510 { make_specialized_arrpackedn(BKeyset, TInt), ival(1), make_specialized_arrmapn(BKeysetN, TInt, TInt), false },
3511 { make_specialized_arrpackedn(BKeysetN, TInt), ival(1), make_specialized_arrpackedn(BKeysetN, TInt), false },
3513 { make_specialized_arrpacked(BVecN, {TObj}), TStr, make_specialized_arrpacked(BVecN, {TObj, TStr}), false },
3514 { make_specialized_arrpacked(BSVecN, {TInt}), TStr, make_specialized_arrpacked(BVecN, {TInt, TStr}), false },
3515 { make_specialized_arrpacked(BVec, {TObj}), TStr, make_specialized_arrpackedn(BVecN, Type{BStr|BObj}), false },
3516 { make_specialized_arrpacked(BSVec, {TInt}), TStr, make_specialized_arrpackedn(BVecN, TArrKey), false },
3517 { make_specialized_arrpacked(BKeysetN, {ival(0)}), TStr, TKeysetN, false },
3518 { make_specialized_arrpacked(BKeysetN, {ival(0),ival(1)}), TStr, TKeysetN, false },
3519 { make_specialized_arrpacked(BKeyset, {ival(0)}), sval(s_A),
3520 make_specialized_arrmapn(BKeysetN, union_of(TInt,sval(s_A)), union_of(TInt,sval(s_A))), false },
3521 { make_specialized_arrpacked(BKeyset, {ival(0), ival(1)}), sval(s_A),
3522 make_specialized_arrmapn(BKeysetN, union_of(TInt,sval(s_A)), union_of(TInt,sval(s_A))), false },
3523 { make_specialized_arrpacked(BKeysetN, {ival(0)}), sval(s_A), make_specialized_arrmap(BKeysetN, mapElem9), false },
3524 { make_specialized_arrpacked(BKeysetN, {ival(0),ival(1)}), sval(s_A), make_specialized_arrmap(BKeysetN, mapElem10), false },
3525 { make_specialized_arrpacked(BKeysetN, {ival(0)}), sval_nonstatic(s_A), make_specialized_arrmap(BKeysetN, mapElem11), false },
3526 { make_specialized_arrpacked(BKeysetN, {ival(0),ival(1)}), sval_nonstatic(s_A), make_specialized_arrmap(BKeysetN, mapElem12), false },
3527 { make_specialized_arrpacked(BKeyset, {ival(0)}), ival(-1), make_specialized_arrmapn(BKeysetN, TInt, TInt), false },
3528 { make_specialized_arrpacked(BKeysetN, {ival(0)}), ival(-1), make_specialized_arrmap(BKeysetN, mapElem13), false },
3529 { make_specialized_arrpacked(BKeysetN, {ival(0),ival(1)}), ival(0), make_specialized_arrpacked(BKeysetN, {ival(0),ival(1)}), false },
3530 { make_specialized_arrpacked(BKeysetN, {ival(0),ival(1)}), ival(1), make_specialized_arrpacked(BKeysetN, {ival(0),ival(1)}), false },
3531 { make_specialized_arrpacked(BKeysetN, {ival(0),ival(1)}), ival(2), make_specialized_arrpacked(BKeysetN, {ival(0),ival(1),ival(2)}), false },
3532 { make_specialized_arrpacked(BKeyset, {ival(0),ival(1)}), ival(3), make_specialized_arrmapn(BKeysetN, TInt, TInt), false },
3533 { make_specialized_arrpacked(BKeysetN, {ival(0),ival(1)}), ival(3), make_specialized_arrmap(BKeysetN, mapElem14), false },
3534 { make_specialized_arrpacked(BKeyset, {ival(0)}), ival(0), make_specialized_arrpacked(BKeysetN, {ival(0)}), false },
3535 { make_specialized_arrpacked(BKeyset, {ival(0),ival(1)}), ival(0), make_specialized_arrpackedn(BKeysetN, TInt), false },
3536 { make_specialized_arrpacked(BKeyset, {ival(0)}), ival(1), make_specialized_arrmapn(BKeysetN, TInt, TInt), false },
3538 { make_specialized_arrmapn(BDictN, TInt, TObj), TStr, make_specialized_arrmapn(BDictN, TInt, Type{BObj|BStr}), true },
3539 { make_specialized_arrmapn(BSDictN, TSStr, TSStr), TInt, make_specialized_arrmapn(BDictN, TUncArrKey, TUncArrKey), true },
3540 { make_specialized_arrmapn(BDict, TArrKey, TStr), Type{BInitCell & ~BStr}, TDictN, true },
3541 { make_specialized_arrmapn(BDict, TStr, TInitCell), TInitCell, TDictN, true },
3542 { make_specialized_arrmapn(BKeysetN, TInt, TInt), TStr, TKeysetN, false },
3543 { make_specialized_arrmapn(BKeyset, TInt, TInt), TStr, TKeysetN, false },
3544 { make_specialized_arrmapn(BKeysetN, TCStr, TCStr), TSStr, make_specialized_arrmapn(BKeysetN, TStr, TStr), false },
3545 { make_specialized_arrmapn(BKeyset, TCStr, TCStr), TSStr, make_specialized_arrmapn(BKeysetN, TStr, TStr), false },
3547 { make_specialized_arrmap(BDictN, mapElem1), TFalse, make_specialized_arrmap(BDictN, mapElem4), false },
3548 { make_specialized_arrmap(BDictN, mapElem2), TInitCell, make_specialized_arrmap(BDictN, mapElem5), false },
3549 { make_specialized_arrmap(BDictN, mapElem3), TFalse, make_specialized_arrmap(BDictN, mapElem3), true },
3550 { make_specialized_arrmap(BDictN, mapElem1, TStr, TInt),
3551 TFalse, make_specialized_arrmap(BDictN, mapElem1, TArrKey, Type{BInt|BFalse}), true },
3552 { make_specialized_arrmap(BDictN, mapElem1, ival(10), TInt),
3553 TFalse, make_specialized_arrmap(BDictN, mapElem1, TInt, Type{BInt|BFalse}), false },
3554 { make_specialized_arrmap(BDictN, mapElem1, ival(std::numeric_limits<int64_t>::max()), TInt),
3555 TFalse, make_specialized_arrmap(BDictN, mapElem1, TInt, Type{BInt|BFalse}), true },
3556 { make_specialized_arrmap(BDict, mapElem1), TFalse,
3557 make_specialized_arrmapn(BDictN, TUncArrKey, Type{BInt|BObj|BFalse}), false },
3558 { make_specialized_arrmap(BDict, mapElem3), TFalse,
3559 make_specialized_arrmapn(BDictN, TInt, TInitCell), true },
3560 { make_specialized_arrmap(BKeysetN, mapElem10), TInt, make_specialized_arrmap(BKeysetN, mapElem10, TInt, TInt), false },
3561 { make_specialized_arrmap(BKeysetN, mapElem10), TSStr, make_specialized_arrmap(BKeysetN, mapElem10, TSStr, TSStr), false },
3562 { make_specialized_arrmap(BKeysetN, mapElem10, TInt, TInt), TStr, make_specialized_arrmap(BKeysetN, mapElem10, TArrKey, TArrKey), false },
3563 { make_specialized_arrmap(BKeysetN, mapElem10), ival(1), make_specialized_arrmap(BKeysetN, mapElem10), false },
3564 { make_specialized_arrmap(BKeysetN, mapElem10), sval(s_A), make_specialized_arrmap(BKeysetN, mapElem10), false },
3565 { make_specialized_arrmap(BKeysetN, mapElem10), sval_nonstatic(s_A), make_specialized_arrmap(BKeysetN, mapElem10), false },
3566 { make_specialized_arrmap(BKeysetN, mapElem10), ival(100), make_specialized_arrmap(BKeysetN, mapElem15), false },
3567 { make_specialized_arrmap(BKeysetN, mapElem10), sval_nonstatic(s_B), make_specialized_arrmap(BKeysetN, mapElem16), false },
3568 { make_specialized_arrmap(BKeysetN, mapElem10, TStr, TStr), ival(100),
3569 make_specialized_arrmap(BKeysetN, mapElem10, union_of(ival(100),TStr), union_of(ival(100),TStr)), false },
3570 { make_specialized_arrmap(BKeysetN, mapElem10, TInt, TInt), sval(s_B),
3571 make_specialized_arrmap(BKeysetN, mapElem10, union_of(TInt,sval(s_B)), union_of(TInt,sval(s_B))), false },
3572 { make_specialized_arrmap(BKeysetN, mapElem10, ival(100), ival(100)), TStr,
3573 make_specialized_arrmap(BKeysetN, mapElem10, union_of(ival(100),TStr), union_of(ival(100),TStr)), false },
3574 { make_specialized_arrmap(BKeysetN, mapElem10, ival(100), ival(100)), ival(100), make_specialized_arrmap(BKeysetN, mapElem15), false },
3575 { make_specialized_arrmap(BKeysetN, mapElem10, sval(s_B), sval(s_B)), sval(s_B), make_specialized_arrmap(BKeysetN, mapElem17), false },
3576 { make_specialized_arrmap(BKeysetN, mapElem10, sval(s_B), sval(s_B)), sval_nonstatic(s_B), make_specialized_arrmap(BKeysetN, mapElem16), false },
3577 { make_specialized_arrmap(BKeyset, mapElem10), TInt, make_specialized_arrmapn(BKeysetN, union_of(sval(s_A),TInt), union_of(sval(s_A),TInt)), false },
3578 { make_specialized_arrmap(BKeyset, mapElem16), TStr, TKeysetN, false },
3579 { make_specialized_arrmap(BKeyset, mapElem7), TStr, TKeysetN, false },
3580 { make_specialized_arrmap(BKeyset, mapElem10), ival(1), make_specialized_arrmapn(BKeysetN, union_of(sval(s_A),TInt), union_of(sval(s_A),TInt)), false },
3581 { make_specialized_arrmap(BKeyset, mapElem10), ival(0), make_specialized_arrmapn(BKeysetN, union_of(sval(s_A),TInt), union_of(sval(s_A),TInt)), false },
3582 { make_specialized_arrmap(BKeyset, mapElem7), ival(1), make_specialized_arrmap(BKeysetN, mapElem7), false },
3583 { make_specialized_arrmap(BKeyset, mapElem18), ival(1), make_specialized_arrmap(BKeysetN, mapElem7, sval(s_A), sval(s_A)), false },
3584 { make_specialized_arrmap(BKeyset, mapElem8), sval_nonstatic(s_A), make_specialized_arrmap(BKeysetN, mapElem19), false },
3585 { make_specialized_arrmap(BKeysetN, mapElem7), union_of(ival(1),TStr), make_specialized_arrmap(BKeysetN, mapElem7, TArrKey, TArrKey), false },
3588 auto old = RO::EvalRaiseClassConversionWarning;
3589 RO::EvalRaiseClassConversionWarning = true;
3590 SCOPE_EXIT { RO::EvalRaiseClassConversionWarning = old; };
3592 for (auto const& t : tests) {
3593 auto const elem = array_like_newelem(std::get<0>(t), std::get<1>(t));
3594 EXPECT_EQ(loosen_mark_for_testing(elem.first), std::get<2>(t));
3595 EXPECT_EQ(elem.second, std::get<3>(t));
3599 TEST(Type, ArrayLikeSetElem) {
3600 auto const program = make_test_program();
3601 Index index { program.get() };
3603 const std::vector<Type> keys{
3604 TInt,
3605 TStr,
3606 TSStr,
3607 TCStr,
3608 TArrKey,
3609 TUncArrKey,
3610 sval(s_A),
3611 sval(s_B),
3612 sval(s_C),
3613 sval_nonstatic(s_A),
3614 sval_counted(s_A),
3615 ival(0),
3616 ival(1),
3617 ival(123),
3618 ival(777),
3619 ival(-1),
3620 ival(std::numeric_limits<int64_t>::max()),
3621 union_of(sval(s_A),TInt),
3622 union_of(sval(s_B),TInt),
3623 union_of(sval(s_C),TInt),
3624 union_of(sval_counted(s_A),TInt),
3625 union_of(ival(0),TStr),
3626 union_of(ival(1),TStr),
3627 union_of(ival(123),TStr),
3628 union_of(ival(777),TStr),
3629 union_of(ival(-1),TStr),
3630 union_of(ival(std::numeric_limits<int64_t>::max()),TStr)
3633 const std::vector<Type> values{
3634 TInt,
3635 TStr,
3636 TSStr,
3637 TObj,
3638 TInitUnc,
3639 TInitCell
3642 auto const& all = allCases(index);
3643 for (auto const& t : all) {
3644 if (!t.subtypeOf(BCell) || !t.couldBe(BArrLike)) continue;
3646 for (auto const& k : keys) {
3647 for (auto const& v : values) {
3648 auto const set = array_like_set(t, k, v);
3649 EXPECT_FALSE(set.first.couldBe(BArrLikeE));
3651 if (!set.first.couldBe(BArrLike)) {
3652 EXPECT_TRUE(set.second);
3653 } else {
3654 EXPECT_FALSE(set.first.subtypeAmong(BSArrLike, BArrLike));
3657 if (t.subtypeAmong(BKeyset, BArrLike)) {
3658 EXPECT_FALSE(set.first.couldBe(BArrLike));
3660 if (t.couldBe(BKeyset)) {
3661 EXPECT_TRUE(set.second);
3663 if (t.subtypeAmong(BDict, BArrLike)) {
3664 EXPECT_FALSE(set.second);
3666 if (t.subtypeAmong(BVec, BArrLike)) {
3667 if (!k.couldBe(BInt) || !t.couldBe(BVecN)) {
3668 EXPECT_FALSE(set.first.couldBe(BArrLike));
3672 if (set.first.couldBe(BArrLike)) {
3673 EXPECT_TRUE(v.subtypeOf(array_like_elem(set.first, k).first));
3676 auto [arr, rest] = split_array_like(t);
3677 auto const set2 = array_like_set(arr, k, v);
3678 EXPECT_EQ(set.first, union_of(set2.first, rest));
3679 EXPECT_EQ(set.second, set2.second);
3684 auto const mapElem1 = MapElems{
3685 map_elem(s_A, TObj)
3687 auto const mapElem2 = MapElems{
3688 map_elem_nonstatic(s_A, TObj)
3690 auto const mapElem3 = MapElems{
3691 map_elem(int64_t(0), TInt),
3692 map_elem(1, TObj),
3693 map_elem(s_A, TFalse)
3695 auto const mapElem4 = MapElems{
3696 map_elem(int64_t(0), TInt),
3697 map_elem(-1, TStr)
3699 auto const mapElem5 = MapElems{
3700 map_elem(int64_t(0), TInt),
3701 map_elem(2, TStr)
3703 auto const mapElem6 = MapElems{
3704 map_elem(s_A, TInt),
3705 map_elem(s_B, TObj),
3706 map_elem(100, TFalse)
3708 auto const mapElem7 = MapElems{
3709 map_elem_counted(s_A, TInt),
3710 map_elem_counted(s_B, TObj),
3711 map_elem(100, TFalse)
3713 auto const mapElem8 = MapElems{
3714 map_elem(s_A, Type{BInt|BTrue}),
3715 map_elem(s_B, Type{BObj|BTrue}),
3716 map_elem(100, TFalse)
3718 auto const mapElem9 = MapElems{
3719 map_elem_counted(s_A, Type{BInt|BTrue}),
3720 map_elem_counted(s_B, Type{BObj|BTrue}),
3721 map_elem(100, TFalse)
3723 auto const mapElem10 = MapElems{
3724 map_elem(s_A, TInt),
3725 map_elem(s_B, TObj),
3726 map_elem(100, TBool)
3728 auto const mapElem11 = MapElems{
3729 map_elem(s_A, TInt),
3730 map_elem(s_B, TFalse),
3731 map_elem(100, TFalse)
3733 auto const mapElem12 = MapElems{
3734 map_elem_counted(s_A, TInt),
3735 map_elem_counted(s_B, TFalse),
3736 map_elem(100, TFalse)
3738 auto const mapElem13 = MapElems{
3739 map_elem(s_A, TInt),
3740 map_elem(s_B, TObj),
3741 map_elem(100, TFalse),
3742 map_elem(s_BA, TInt)
3744 auto const mapElem14 = MapElems{
3745 map_elem(s_A, TInt),
3746 map_elem(s_B, TObj),
3747 map_elem(100, TFalse),
3748 map_elem_counted(s_BA, TInt)
3750 auto const mapElem15 = MapElems{
3751 map_elem(s_A, TInt),
3752 map_elem(s_B, TObj),
3753 map_elem(100, TFalse),
3754 map_elem(s_BA, TTrue)
3756 auto const mapElem16 = MapElems{
3757 map_elem(s_A, TInt),
3758 map_elem(s_B, TObj),
3759 map_elem(100, TFalse),
3760 map_elem_nonstatic(s_BA, TTrue)
3762 auto const mapElem17 = MapElems{
3763 map_elem(s_A, TStr)
3765 auto const mapElem18 = MapElems{
3766 map_elem_nonstatic(s_A, TStr)
3768 auto const mapElem19 = MapElems{
3769 map_elem(s_A, union_of(ival(100),TFalse)),
3770 map_elem(s_B, union_of(ival(200),TFalse))
3772 auto const mapElem20 = MapElems{
3773 map_elem(s_A, ival(100)),
3774 map_elem(s_B, ival(300))
3776 auto const mapElem21 = MapElems{
3777 map_elem(1, TSStr)
3779 auto const mapElem22 = MapElems{
3780 map_elem(1, TUncArrKey)
3783 auto const staticVec1 = static_vec(s_A, s_B, 100);
3784 auto const staticDict1 = static_dict(s_A, 100, s_B, 200);
3786 const std::vector<std::tuple<Type, Type, Type, Type, bool>> tests{
3787 { TVecN, TStr, TInitCell, TBottom, true },
3788 { TVecE, TStr, TInitCell, TBottom, true },
3789 { TVec, TStr, TInitCell, TBottom, true },
3790 { TVecE, TInt, TInitCell, TBottom, true },
3791 { TVecN, ival(-1), TInitCell, TBottom, true },
3792 { TSVec, TInt, TInitCell, TVecN, true },
3793 { TSVecN, TInt, TInitCell, TVecN, true },
3794 { TVec, TInt, TInitCell, TVecN, true },
3795 { TVecN, TInt, TInitCell, TVecN, true },
3796 { TVecN, ival(0), TInitCell, TVecN, true },
3797 { TDictE, TInt, TStr, make_specialized_arrmapn(BDictN, TInt, TStr), false },
3798 { TSDictE, TInt, TStr, make_specialized_arrmapn(BDictN, TInt, TStr), false },
3799 { TCDictE, TInt, TStr, make_specialized_arrmapn(BDictN, TInt, TStr), false },
3800 { TDictE, TArrKey, TInitCell, TDictN, false },
3801 { TDictE, ival(0), TObj, make_specialized_arrpacked(BDictN, {TObj}), false },
3802 { TDictE, sval(s_A), TObj, make_specialized_arrmap(BDictN, mapElem1), false },
3803 { TDictE, sval_nonstatic(s_A), TObj, make_specialized_arrmap(BDictN, mapElem2), false },
3804 { TDictN, TInt, TStr, TDictN, false },
3805 { TDict, TInt, TStr, TDictN, false },
3806 { TSDict, TInt, TStr, TDictN, false },
3807 { TSDictN, TInt, TStr, TDictN, false },
3808 { TKeysetN, TArrKey, TArrKey, TBottom, true },
3809 { TKeysetE, TArrKey, TArrKey, TBottom, true },
3810 { TKeyset, TArrKey, TArrKey, TBottom, true },
3811 { TSKeysetN, TArrKey, TArrKey, TBottom, true },
3812 { TSKeysetE, TArrKey, TArrKey, TBottom, true },
3813 { TSKeyset, TArrKey, TArrKey, TBottom, true },
3815 { make_specialized_arrval(BSVecN, staticVec1), TInt, TFalse,
3816 make_specialized_arrpacked(BVecN, {union_of(sval(s_A),TFalse),union_of(sval(s_B),TFalse),union_of(ival(100),TFalse)}), true },
3817 { make_specialized_arrval(BSVecN, staticVec1), ival(1), TFalse,
3818 make_specialized_arrpacked(BVecN, {sval(s_A),TFalse,ival(100)}), false },
3819 { make_specialized_arrval(BSDictN, staticDict1), TStr, TFalse, make_specialized_arrmap(BDictN, mapElem19, TStr, TFalse), false },
3820 { make_specialized_arrval(BSDictN, staticDict1), sval(s_B), ival(300), make_specialized_arrmap(BDictN, mapElem20), false },
3822 { make_specialized_arrpackedn(BVecN, TObj), TInt, TStr, make_specialized_arrpackedn(BVecN, Type{BObj|BStr}), true },
3823 { make_specialized_arrpackedn(BVecN, Type{BInitCell & ~BObj}), TInt, TObj, TVecN, true },
3824 { make_specialized_arrpackedn(BVecN, TObj), ival(-1), TStr, TBottom, true },
3825 { make_specialized_arrpackedn(BVecN, TObj), ival(0), TStr, make_specialized_arrpackedn(BVecN, Type{BObj|BStr}), false },
3826 { make_specialized_arrpackedn(BVec, TObj), ival(0), TStr, make_specialized_arrpackedn(BVecN, Type{BObj|BStr}), true },
3827 { make_specialized_arrpackedn(BVecN, TObj), ival(1), TStr, make_specialized_arrpackedn(BVecN, Type{BObj|BStr}), true },
3828 { make_specialized_arrpackedn(BVecN, TObj), union_of(ival(0),TStr), TStr, make_specialized_arrpackedn(BVecN, Type{BObj|BStr}), true },
3829 { make_specialized_arrpackedn(BDictN, TObj), TInt, TStr, make_specialized_arrmapn(BDictN, TInt, Type{BObj|BStr}), false },
3830 { make_specialized_arrpackedn(BDictN, Type{BInitCell & ~BObj}), TArrKey, TObj, TDictN, false },
3831 { make_specialized_arrpackedn(BDictN, TInitCell), TArrKey, TInitCell, TDictN, false },
3832 { make_specialized_arrpackedn(BDictN, TObj), sval(s_A), TObj, make_specialized_arrmapn(BDictN, union_of(TInt,sval(s_A)), TObj), false },
3833 { make_specialized_arrpackedn(BDictN, TObj), ival(0), TStr, make_specialized_arrpackedn(BDictN, Type{BObj|BStr}), false },
3834 { make_specialized_arrpackedn(BDictN, TObj), ival(1), TStr, make_specialized_arrpackedn(BDictN, Type{BObj|BStr}), false },
3835 { make_specialized_arrpackedn(BDict, TObj), ival(1), TStr, make_specialized_arrmapn(BDictN, TInt, Type{BObj|BStr}), false },
3837 { make_specialized_arrpacked(BVecN, {TStr}), TInt, TInt, make_specialized_arrpacked(BVecN, {TArrKey}), true },
3838 { make_specialized_arrpacked(BVecN, {TStr, TObj}), TInt, TInt, make_specialized_arrpacked(BVecN, {TArrKey, Type{BObj|BInt}}), true },
3839 { make_specialized_arrpacked(BVecN, {TStr}), ival(-1), TInt, TBottom, true },
3840 { make_specialized_arrpacked(BVecN, {TStr}), ival(1), TInt, TBottom, true },
3841 { make_specialized_arrpacked(BVecN, {TStr, TObj}), ival(1), TInt, make_specialized_arrpacked(BVecN, {TStr, TInt}), false },
3842 { make_specialized_arrpacked(BVec, {TStr, TObj}), ival(1), TInt, make_specialized_arrpacked(BVecN, {TStr, TInt}), true },
3843 { make_specialized_arrpacked(BVecN, {TStr, TObj}), union_of(ival(1),TStr), TInt, make_specialized_arrpacked(BVecN, {TArrKey, Type{BInt|BObj}}), true },
3844 { make_specialized_arrpacked(BDictN, {TObj}), TInt, TStr, make_specialized_arrmapn(BDictN, TInt, Type{BObj|BStr}), false },
3845 { make_specialized_arrpacked(BDictN, {TObj}), TStr, TObj, make_specialized_arrmapn(BDictN, union_of(ival(0),TStr), TObj), false },
3846 { make_specialized_arrpacked(BDictN, {TInitCell}), TStr, TInitCell, TDictN, false },
3847 { make_specialized_arrpacked(BDictN, {TInitCell, TInitCell}), TStr, TInitCell, TDictN, false },
3848 { make_specialized_arrpacked(BDictN, {TInt, TObj}), sval(s_A), TFalse, make_specialized_arrmap(BDictN, mapElem3), false },
3849 { make_specialized_arrpacked(BDict, {TInt, TObj}), sval(s_A), TFalse, make_specialized_arrmapn(BDictN, union_of(TInt,sval(s_A)), Type{BInt|BObj|BFalse}), false },
3850 { make_specialized_arrpacked(BDictN, {TInt}), ival(-1), TStr, make_specialized_arrmap(BDictN, mapElem4), false },
3851 { make_specialized_arrpacked(BDictN, {TInt}), ival(2), TStr, make_specialized_arrmap(BDictN, mapElem5), false },
3852 { make_specialized_arrpacked(BDict, {TInt}), ival(-1), TStr, make_specialized_arrmapn(BDictN, TInt, TArrKey), false },
3853 { make_specialized_arrpacked(BDict, {TInt}), ival(2), TStr, make_specialized_arrmapn(BDictN, TInt, TArrKey), false },
3854 { make_specialized_arrpacked(BDictN, {TInt}), ival(0), TStr, make_specialized_arrpacked(BDictN, {TStr}), false },
3855 { make_specialized_arrpacked(BDictN, {TInt}), ival(1), TStr, make_specialized_arrpacked(BDictN, {TInt, TStr}), false },
3857 { make_specialized_arrmapn(BDictN, TStr, TInt), TStr, TStr, make_specialized_arrmapn(BDictN, TStr, TArrKey), false },
3858 { make_specialized_arrmapn(BDictN, TStr, TInt), TInt, TInt, make_specialized_arrmapn(BDictN, TArrKey, TInt), false },
3859 { make_specialized_arrmapn(BDictN, TStr, Type{BInitCell & ~BObj}), TInt, TObj, TDictN, false },
3860 { make_specialized_arrmapn(BDict, TStr, TInt), TStr, TStr, make_specialized_arrmapn(BDictN, TStr, TArrKey), false },
3861 { make_specialized_arrmapn(BDict, TStr, TInt), TInt, TInt, make_specialized_arrmapn(BDictN, TArrKey, TInt), false },
3862 { make_specialized_arrmapn(BDict, TStr, Type{BInitCell & ~BObj}), TInt, TObj, TDictN, false },
3864 { make_specialized_arrmap(BDictN, mapElem6), TStr, TTrue, make_specialized_arrmap(BDictN, mapElem8, TStr, TTrue), false },
3865 { make_specialized_arrmap(BDictN, mapElem6), TCStr, TTrue, make_specialized_arrmap(BDictN, mapElem8, TCStr, TTrue), false },
3866 { make_specialized_arrmap(BDictN, mapElem6), TSStr, TTrue, make_specialized_arrmap(BDictN, mapElem8, TSStr, TTrue), false },
3867 { make_specialized_arrmap(BDictN, mapElem7), TStr, TTrue, make_specialized_arrmap(BDictN, mapElem9, TStr, TTrue), false },
3868 { make_specialized_arrmap(BDictN, mapElem7), TCStr, TTrue, make_specialized_arrmap(BDictN, mapElem9, TCStr, TTrue), false },
3869 { make_specialized_arrmap(BDictN, mapElem7), TSStr, TTrue, make_specialized_arrmap(BDictN, mapElem9, TSStr, TTrue), false },
3870 { make_specialized_arrmap(BDictN, mapElem6), TInt, TTrue, make_specialized_arrmap(BDictN, mapElem10, TInt, TTrue), false },
3871 { make_specialized_arrmap(BDictN, mapElem6), sval(s_B), TFalse, make_specialized_arrmap(BDictN, mapElem11), false },
3872 { make_specialized_arrmap(BDictN, mapElem6), sval_nonstatic(s_B), TFalse, make_specialized_arrmap(BDictN, mapElem11), false },
3873 { make_specialized_arrmap(BDictN, mapElem6), sval_counted(s_B), TFalse, make_specialized_arrmap(BDictN, mapElem11), false },
3874 { make_specialized_arrmap(BDictN, mapElem7), sval(s_B), TFalse, make_specialized_arrmap(BDictN, mapElem12), false },
3875 { make_specialized_arrmap(BDictN, mapElem7), sval_nonstatic(s_B), TFalse, make_specialized_arrmap(BDictN, mapElem12), false },
3876 { make_specialized_arrmap(BDictN, mapElem7), sval_counted(s_B), TFalse, make_specialized_arrmap(BDictN, mapElem12), false },
3877 { make_specialized_arrmap(BDictN, mapElem6), sval(s_BA), TInt, make_specialized_arrmap(BDictN, mapElem13), false },
3878 { make_specialized_arrmap(BDictN, mapElem6), sval_counted(s_BA), TInt, make_specialized_arrmap(BDictN, mapElem14), false },
3879 { make_specialized_arrmap(BDictN, mapElem6, TInt, TTrue), sval(s_BA), TFalse,
3880 make_specialized_arrmap(BDictN, mapElem6, union_of(TInt,sval(s_BA)), TBool), false },
3881 { make_specialized_arrmap(BDictN, mapElem6, sval(s_BA), TFalse), sval(s_BA), TTrue,
3882 make_specialized_arrmap(BDictN, mapElem15), false },
3883 { make_specialized_arrmap(BDictN, mapElem6, sval_counted(s_BA), TFalse), sval(s_BA), TTrue,
3884 make_specialized_arrmap(BDictN, mapElem16), false },
3885 { make_specialized_arrmap(BDictN, mapElem6, sval(s_BA), TFalse), sval_counted(s_BA), TTrue,
3886 make_specialized_arrmap(BDictN, mapElem16), false },
3887 { make_specialized_arrmap(BDict, mapElem6), TStr, TTrue,
3888 make_specialized_arrmapn(BDictN, union_of(ival(100),TStr), Type{BInt|BObj|BBool}), false },
3889 { make_specialized_arrmap(BDict, mapElem6), TSStr, TTrue,
3890 make_specialized_arrmapn(BDictN, union_of(ival(100),TSStr), Type{BInt|BObj|BBool}), false },
3891 { make_specialized_arrmap(BDict, mapElem6), TCStr, TTrue,
3892 make_specialized_arrmapn(BDictN, union_of(ival(100),TStr), Type{BInt|BObj|BBool}), false },
3893 { make_specialized_arrmap(BDict, mapElem7), TStr, TTrue,
3894 make_specialized_arrmapn(BDictN, union_of(ival(100),TStr), Type{BInt|BObj|BBool}), false },
3895 { make_specialized_arrmap(BDict, mapElem7), TSStr, TTrue,
3896 make_specialized_arrmapn(BDictN, union_of(ival(100),TStr), Type{BInt|BObj|BBool}), false },
3897 { make_specialized_arrmap(BDict, mapElem7), TCStr, TTrue,
3898 make_specialized_arrmapn(BDictN, union_of(ival(100),TCStr), Type{BInt|BObj|BBool}), false },
3899 { make_specialized_arrmap(BDict, mapElem6), sval(s_A), TStr,
3900 make_specialized_arrmap(BDictN, mapElem17, union_of(TInt,sval(s_B)), Type{BObj|BFalse}), false },
3901 { make_specialized_arrmap(BDict, mapElem6), sval_counted(s_A), TStr,
3902 make_specialized_arrmap(BDictN, mapElem18, union_of(TInt,sval(s_B)), Type{BObj|BFalse}), false },
3903 { make_specialized_arrmap(BDict, mapElem6, TInt, TTrue), sval(s_A), TStr,
3904 make_specialized_arrmap(BDictN, mapElem17, union_of(TInt,sval(s_B)), Type{BObj|BBool}), false },
3905 { make_specialized_arrmap(BDictN, mapElem21), union_of(ival(1),TStr), TInt,
3906 make_specialized_arrmap(BDictN, mapElem22, TArrKey, TInt), false },
3908 for (auto const& t : tests) {
3909 auto const elem = array_like_set(std::get<0>(t), std::get<1>(t), std::get<2>(t));
3910 EXPECT_EQ(loosen_mark_for_testing(elem.first), std::get<3>(t));
3911 EXPECT_EQ(elem.second, std::get<4>(t));
3915 TEST(Type, SpecificExamples) {
3916 // Random examples to stress option types, values, etc:
3918 EXPECT_TRUE(!TInt.subtypeOf(ival(1)));
3920 EXPECT_TRUE(TInitCell.couldBe(ival(1)));
3921 EXPECT_TRUE(ival(2).subtypeOf(BInt));
3922 EXPECT_TRUE(!ival(2).subtypeOf(BBool));
3923 EXPECT_TRUE(ival(3).subtypeOf(BInt));
3924 EXPECT_TRUE(TInt.subtypeOf(BInt));
3925 EXPECT_TRUE(!TBool.subtypeOf(BInt));
3926 EXPECT_TRUE(TInitNull.subtypeOf(BOptInt));
3927 EXPECT_TRUE(!TNull.subtypeOf(BOptInt));
3928 EXPECT_TRUE(TNull.couldBe(BOptInt));
3929 EXPECT_TRUE(TNull.couldBe(BOptBool));
3931 EXPECT_TRUE(TInitNull.subtypeOf(BInitCell));
3932 EXPECT_TRUE(TInitNull.subtypeOf(BCell));
3933 EXPECT_TRUE(!TUninit.subtypeOf(BInitNull));
3935 EXPECT_TRUE(ival(3).subtypeOf(BInt));
3936 EXPECT_TRUE(ival(3).subtypeOf(opt(ival(3))));
3937 EXPECT_TRUE(ival(3).couldBe(opt(ival(3))));
3938 EXPECT_TRUE(ival(3).couldBe(BInt));
3939 EXPECT_TRUE(TInitNull.couldBe(opt(ival(3))));
3940 EXPECT_TRUE(TNull.couldBe(opt(ival(3))));
3941 EXPECT_TRUE(TInitNull.subtypeOf(opt(ival(3))));
3942 EXPECT_TRUE(!TNull.subtypeOf(opt(ival(3))));
3944 EXPECT_EQ(intersection_of(TClsMeth, TInitUnc), TClsMeth);
3946 auto const test_map_a = MapElems{map_elem(s_A, TDbl), map_elem(s_B, TBool)};
3947 auto const test_map_b = MapElems{map_elem(s_A, TObj), map_elem(s_B, TRes)};
3949 auto const disjointArrSpecs = std::vector<Type>{
3950 dict_packedn(TInt),
3951 dict_packedn(TStr),
3952 dict_packed({TDbl}),
3953 dict_packed({TBool}),
3954 dict_n(TStr, TStr),
3955 dict_n(TStr, TInt),
3956 dict_map(test_map_a),
3957 dict_map(test_map_b)
3959 for (auto const& t1 : disjointArrSpecs) {
3960 for (auto const& t2 : disjointArrSpecs) {
3961 if (t1 == t2) continue;
3962 EXPECT_FALSE(t1.couldBe(t2));
3963 EXPECT_FALSE(t2.couldBe(t1));
3965 auto const t3 = union_of(t1, TDictE);
3966 auto const t4 = union_of(t2, TDictE);
3967 EXPECT_TRUE(t3.couldBe(t4));
3968 EXPECT_TRUE(t4.couldBe(t3));
3969 EXPECT_FALSE(t3.subtypeOf(t4));
3970 EXPECT_FALSE(t4.subtypeOf(t3));
3971 EXPECT_EQ(intersection_of(t3, t4), TDictE);
3972 EXPECT_EQ(intersection_of(t4, t3), TDictE);
3974 auto const t5 = opt(t1);
3975 auto const t6 = opt(t2);
3976 EXPECT_TRUE(t5.couldBe(t6));
3977 EXPECT_TRUE(t6.couldBe(t5));
3978 EXPECT_FALSE(t5.subtypeOf(t6));
3979 EXPECT_FALSE(t6.subtypeOf(t5));
3980 EXPECT_EQ(intersection_of(t5, t6), TInitNull);
3981 EXPECT_EQ(intersection_of(t6, t5), TInitNull);
3983 auto const t7 = opt(t3);
3984 auto const t8 = opt(t4);
3985 EXPECT_TRUE(t7.couldBe(t8));
3986 EXPECT_TRUE(t8.couldBe(t7));
3987 EXPECT_FALSE(t7.subtypeOf(t8));
3988 EXPECT_FALSE(t8.subtypeOf(t7));
3989 EXPECT_EQ(intersection_of(t7, t8), opt(TDictE));
3990 EXPECT_EQ(intersection_of(t8, t7), opt(TDictE));
3995 TEST(Type, IndexBased) {
3996 auto const program = make_test_program();
3997 auto const unit = program->units.back().get();
3998 auto const func = [&]() -> php::Func* {
3999 for (auto& f : unit->funcs) {
4000 if (f->name->isame(s_test.get())) return f.get();
4002 return nullptr;
4003 }();
4004 EXPECT_TRUE(func != nullptr);
4006 auto const ctx = Context { unit, func };
4007 Index idx{program.get()};
4009 auto const cls = idx.resolve_class(ctx, s_TestClass.get());
4010 if (!cls) ADD_FAILURE();
4011 auto const clsBase = idx.resolve_class(ctx, s_Base.get());
4012 if (!clsBase) ADD_FAILURE();
4014 auto const objExactTy = objExact(*cls);
4015 auto const subObjTy = subObj(*cls);
4016 auto const clsExactTy = clsExact(*cls);
4017 auto const subClsTy = subCls(*cls);
4018 auto const objExactBaseTy = objExact(*clsBase);
4019 auto const subObjBaseTy = subObj(*clsBase);
4021 // Basic relationship between the class types and object types.
4022 EXPECT_EQ(objcls(objExactTy), clsExactTy);
4023 EXPECT_EQ(objcls(subObjTy), subClsTy);
4025 // =TestClass <: <=TestClass, and not vice versa.
4026 EXPECT_TRUE(objExactTy.subtypeOf(subObjTy));
4027 EXPECT_TRUE(!subObjTy.subtypeOf(objExactTy));
4028 // =TestClass <: <=TestClass, and not vice versa.
4029 EXPECT_TRUE(clsExactTy.subtypeOf(subClsTy));
4030 EXPECT_TRUE(!subClsTy.subtypeOf(clsExactTy));
4032 // =TestClass couldBe <= TestClass, and vice versa.
4033 EXPECT_TRUE(objExactTy.couldBe(subObjTy));
4034 EXPECT_TRUE(subObjTy.couldBe(objExactTy));
4035 EXPECT_TRUE(clsExactTy.couldBe(subClsTy));
4036 EXPECT_TRUE(subClsTy.couldBe(clsExactTy));
4038 // Foo= and Foo<= are both subtypes of Foo, and couldBe Foo.
4039 EXPECT_TRUE(objExactTy.subtypeOf(BObj));
4040 EXPECT_TRUE(subObjTy.subtypeOf(BObj));
4041 EXPECT_TRUE(objExactTy.couldBe(BObj));
4042 EXPECT_TRUE(subObjTy.couldBe(BObj));
4043 EXPECT_TRUE(TObj.couldBe(objExactTy));
4044 EXPECT_TRUE(TObj.couldBe(subObjTy));
4045 EXPECT_TRUE(clsExactTy.subtypeOf(BCls));
4046 EXPECT_TRUE(subClsTy.subtypeOf(BCls));
4047 EXPECT_TRUE(clsExactTy.couldBe(BCls));
4048 EXPECT_TRUE(subClsTy.couldBe(BCls));
4049 EXPECT_TRUE(TCls.couldBe(clsExactTy));
4050 EXPECT_TRUE(TCls.couldBe(subClsTy));
4052 // These checks are relevant for class to key conversions
4053 EXPECT_TRUE(clsExactTy.subtypeOf(BOptCls | BOptLazyCls));
4054 EXPECT_TRUE(subClsTy.subtypeOf(BOptCls | BOptLazyCls));
4055 EXPECT_TRUE(TCls.subtypeOf(BOptCls | BOptLazyCls));
4056 EXPECT_TRUE(TLazyCls.subtypeOf(BOptCls | BOptLazyCls));
4057 EXPECT_TRUE(clsExactTy.couldBe(BOptCls | BOptLazyCls));
4058 EXPECT_TRUE(subClsTy.couldBe(BOptCls | BOptLazyCls));
4059 auto keyTy1 = union_of(clsExactTy, sval(s_TestClass));
4060 EXPECT_TRUE(keyTy1.couldBe(BOptCls | BOptLazyCls));
4061 auto keyTy2 = union_of(TLazyCls, sval(s_TestClass));
4062 EXPECT_TRUE(keyTy2.couldBe(BOptCls | BOptLazyCls));
4063 EXPECT_FALSE(TSStr.couldBe(BOptCls | BOptLazyCls));
4064 EXPECT_FALSE(TStr.couldBe(BOptCls | BOptLazyCls));
4067 // Obj= and Obj<= both couldBe ?Obj, and vice versa.
4068 EXPECT_TRUE(objExactTy.couldBe(BOptObj));
4069 EXPECT_TRUE(subObjTy.couldBe(BOptObj));
4070 EXPECT_TRUE(TOptObj.couldBe(objExactTy));
4071 EXPECT_TRUE(TOptObj.couldBe(subObjTy));
4073 // Obj= and Obj<= are subtypes of ?Obj.
4074 EXPECT_TRUE(objExactTy.subtypeOf(BOptObj));
4075 EXPECT_TRUE(subObjTy.subtypeOf(BOptObj));
4077 // Obj= is a subtype of ?Obj=, and also ?Obj<=.
4078 EXPECT_TRUE(objExactTy.subtypeOf(opt(objExactTy)));
4079 EXPECT_TRUE(objExactTy.subtypeOf(opt(subObjTy)));
4080 EXPECT_TRUE(!opt(objExactTy).subtypeOf(objExactTy));
4081 EXPECT_TRUE(!opt(subObjTy).subtypeOf(objExactTy));
4083 // Obj= couldBe ?Obj= and ?Obj<=, and vice versa.
4084 EXPECT_TRUE(objExactTy.couldBe(opt(objExactTy)));
4085 EXPECT_TRUE(opt(objExactTy).couldBe(objExactTy));
4086 EXPECT_TRUE(objExactTy.couldBe(opt(subObjTy)));
4087 EXPECT_TRUE(opt(subObjTy).couldBe(objExactTy));
4089 // Obj<= is not a subtype of ?Obj=, it is overlapping but
4090 // potentially contains other types. (We might eventually check
4091 // whether objects are final as part of this, but not right now.)
4092 EXPECT_TRUE(!subObjTy.subtypeOf(opt(objExactTy)));
4093 EXPECT_TRUE(!opt(objExactTy).subtypeOf(subObjTy));
4095 // Obj<= couldBe ?Obj= and vice versa.
4096 EXPECT_TRUE(subObjTy.couldBe(opt(objExactTy)));
4097 EXPECT_TRUE(opt(objExactTy).couldBe(subObjTy));
4099 // ?Obj<=, ?Obj=, ?Foo<= and ?Foo= couldBe each other
4100 EXPECT_TRUE(opt(subObjTy).couldBe(opt(objExactBaseTy)));
4101 EXPECT_TRUE(opt(objExactBaseTy).couldBe(opt(subObjTy)));
4102 EXPECT_TRUE(opt(subObjTy).couldBe(opt(subObjBaseTy)));
4103 EXPECT_TRUE(opt(subObjBaseTy).couldBe(opt(subObjTy)));
4104 EXPECT_TRUE(opt(objExactTy).couldBe(opt(objExactBaseTy)));
4105 EXPECT_TRUE(opt(objExactBaseTy).couldBe(opt(objExactTy)));
4106 EXPECT_TRUE(opt(objExactTy).couldBe(opt(subObjBaseTy)));
4107 EXPECT_TRUE(opt(subObjBaseTy).couldBe(opt(objExactTy)));
4110 TEST(Type, Hierarchies) {
4111 auto const program = make_test_program();
4112 auto const unit = program->units.back().get();
4113 auto const func = [&]() -> php::Func* {
4114 for (auto& f : unit->funcs) {
4115 if (f->name->isame(s_test.get())) return f.get();
4117 return nullptr;
4118 }();
4119 EXPECT_TRUE(func != nullptr);
4121 auto const ctx = Context { unit, func };
4122 Index idx{program.get()};
4124 // load classes in hierarchy
4125 auto const clsBase = idx.resolve_class(ctx, s_Base.get());
4126 if (!clsBase) ADD_FAILURE();
4127 auto const clsA = idx.resolve_class(ctx, s_A.get());
4128 if (!clsA) ADD_FAILURE();
4129 auto const clsB = idx.resolve_class(ctx, s_B.get());
4130 if (!clsB) ADD_FAILURE();
4131 auto const clsAA = idx.resolve_class(ctx, s_AA.get());
4132 if (!clsAA) ADD_FAILURE();
4133 auto const clsAB = idx.resolve_class(ctx, s_AB.get());
4134 if (!clsAB) ADD_FAILURE();
4135 auto const clsBA = idx.resolve_class(ctx, s_BA.get());
4136 if (!clsBA) ADD_FAILURE();
4137 auto const clsBB = idx.resolve_class(ctx, s_BB.get());
4138 if (!clsBB) ADD_FAILURE();
4139 auto const clsBAA = idx.resolve_class(ctx, s_BAA.get());
4140 if (!clsBAA) ADD_FAILURE();
4141 auto const clsTestClass = idx.resolve_class(ctx, s_TestClass.get());
4142 if (!clsTestClass) ADD_FAILURE();
4144 // make *exact type* and *sub type* types and objects for all loaded classes
4145 auto const objExactBaseTy = objExact(*clsBase);
4146 auto const subObjBaseTy = subObj(*clsBase);
4147 auto const clsExactBaseTy = clsExact(*clsBase);
4148 auto const subClsBaseTy = subCls(*clsBase);
4150 auto const objExactATy = objExact(*clsA);
4151 auto const subObjATy = subObj(*clsA);
4152 auto const clsExactATy = clsExact(*clsA);
4153 auto const subClsATy = subCls(*clsA);
4155 auto const objExactAATy = objExact(*clsAA);
4156 auto const subObjAATy = subObj(*clsAA);
4157 auto const clsExactAATy = clsExact(*clsAA);
4158 auto const subClsAATy = subCls(*clsAA);
4160 auto const objExactABTy = objExact(*clsAB);
4161 auto const subObjABTy = subObj(*clsAB);
4162 auto const clsExactABTy = clsExact(*clsAB);
4163 auto const subClsABTy = subCls(*clsAB);
4165 auto const objExactBTy = objExact(*clsB);
4166 auto const subObjBTy = subObj(*clsB);
4167 auto const clsExactBTy = clsExact(*clsB);
4168 auto const subClsBTy = subCls(*clsB);
4170 auto const objExactBATy = objExact(*clsBA);
4171 auto const subObjBATy = subObj(*clsBA);
4172 auto const clsExactBATy = clsExact(*clsBA);
4173 auto const subClsBATy = subCls(*clsBA);
4175 auto const objExactBBTy = objExact(*clsBB);
4176 auto const subObjBBTy = subObj(*clsBB);
4177 auto const clsExactBBTy = clsExact(*clsBB);
4178 auto const subClsBBTy = subCls(*clsBB);
4180 auto const objExactBAATy = objExact(*clsBAA);
4181 auto const subObjBAATy = subObj(*clsBAA);
4182 auto const clsExactBAATy = clsExact(*clsBAA);
4183 auto const subClsBAATy = subCls(*clsBAA);
4185 auto const objExactTestClassTy = objExact(*clsTestClass);
4186 auto const subObjTestClassTy = subObj(*clsTestClass);
4187 auto const clsExactTestClassTy = clsExact(*clsTestClass);
4188 auto const subClsTestClassTy = subCls(*clsTestClass);
4190 // check that type from object and type are the same (obnoxious test)
4191 EXPECT_EQ(objcls(objExactBaseTy), clsExactBaseTy);
4192 EXPECT_EQ(objcls(subObjBaseTy), subClsBaseTy);
4193 EXPECT_EQ(objcls(objExactATy), clsExactATy);
4194 EXPECT_EQ(objcls(subObjATy), subClsATy);
4195 EXPECT_EQ(objcls(objExactAATy), clsExactAATy);
4196 EXPECT_EQ(objcls(subObjAATy), subClsAATy);
4197 EXPECT_EQ(objcls(objExactABTy), clsExactABTy);
4198 EXPECT_EQ(objcls(subObjABTy), subClsABTy);
4199 EXPECT_EQ(objcls(objExactBTy), clsExactBTy);
4200 EXPECT_EQ(objcls(subObjBTy), subClsBTy);
4201 EXPECT_EQ(objcls(objExactBATy), clsExactBATy);
4202 EXPECT_EQ(objcls(subObjBATy), subClsBATy);
4203 EXPECT_EQ(objcls(objExactBBTy), clsExactBBTy);
4204 EXPECT_EQ(objcls(subObjBBTy), subClsBBTy);
4205 EXPECT_EQ(objcls(objExactBAATy), clsExactBAATy);
4206 EXPECT_EQ(objcls(subObjBAATy), subClsBAATy);
4208 // both subobj(A) and subcls(A) of no_override class A change to exact types
4209 EXPECT_EQ(objcls(objExactABTy), subClsABTy);
4210 EXPECT_EQ(objcls(subObjABTy), clsExactABTy);
4212 // a T= is a subtype of itself but not a strict subtype
4213 // also a T= is in a "could be" relationship with itself.
4214 EXPECT_TRUE(objcls(objExactBaseTy).subtypeOf(clsExactBaseTy));
4215 EXPECT_FALSE(objcls(objExactBaseTy).strictSubtypeOf(objcls(objExactBaseTy)));
4216 EXPECT_TRUE(objcls(objExactBAATy).subtypeOf(clsExactBAATy));
4217 EXPECT_FALSE(clsExactBAATy.strictSubtypeOf(objcls(objExactBAATy)));
4218 EXPECT_TRUE(clsExactBAATy.couldBe(clsExactBAATy));
4220 // Given the hierarchy A <- B <- C where A is the base then:
4221 // B= is not in any subtype relationshipt with a A= or C=.
4222 // Neither they are in "could be" relationships.
4223 // Overall T= sets are always disjoint.
4224 EXPECT_FALSE(objcls(objExactBATy).subtypeOf(clsExactBaseTy));
4225 EXPECT_FALSE(objcls(objExactBATy).subtypeOf(clsExactBTy));
4226 EXPECT_FALSE(objcls(objExactBATy).subtypeOf(clsExactBAATy));
4227 EXPECT_FALSE(clsExactBATy.strictSubtypeOf(objcls(objExactBaseTy)));
4228 EXPECT_FALSE(clsExactBATy.strictSubtypeOf(objcls(objExactBTy)));
4229 EXPECT_FALSE(clsExactBATy.strictSubtypeOf(objcls(objExactBAATy)));
4230 EXPECT_FALSE(clsExactBATy.couldBe(objcls(objExactBaseTy)));
4231 EXPECT_FALSE(objcls(objExactBATy).couldBe(clsExactBTy));
4232 EXPECT_FALSE(clsExactBATy.couldBe(objcls(objExactBAATy)));
4234 // any T= is both a subtype and strict subtype of T<=.
4235 // Given the hierarchy A <- B <- C where A is the base then:
4236 // C= is a subtype and a strict subtype of B<=, ?B<=, A<= and ?A<=.
4237 // The "could be" relationship also holds.
4238 EXPECT_TRUE(objcls(objExactATy).subtypeOf(subClsATy));
4239 EXPECT_TRUE(objcls(objExactBAATy).subtypeOf(subClsBaseTy));
4240 EXPECT_TRUE(objExactBAATy.subtypeOf(opt(subObjBaseTy)));
4241 EXPECT_TRUE(objcls(objExactBAATy).subtypeOf(subClsBTy));
4242 EXPECT_TRUE(objExactBAATy.subtypeOf(opt(subObjBTy)));
4243 EXPECT_TRUE(clsExactBAATy.subtypeOf(objcls(subObjBATy)));
4244 EXPECT_TRUE(objExactBAATy.subtypeOf(opt(subObjBATy)));
4245 EXPECT_TRUE(clsExactBAATy.subtypeOf(objcls(subObjBAATy)));
4246 EXPECT_TRUE(objExactBAATy.subtypeOf(opt(subObjBAATy)));
4247 EXPECT_TRUE(objcls(objExactATy).strictSubtypeOf(subClsATy));
4248 EXPECT_TRUE(objcls(objExactBAATy).strictSubtypeOf(subClsBaseTy));
4249 EXPECT_TRUE(objExactBAATy.strictSubtypeOf(opt(subObjBaseTy)));
4250 EXPECT_TRUE(objcls(objExactBAATy).strictSubtypeOf(subClsBTy));
4251 EXPECT_TRUE(objExactBAATy.strictSubtypeOf(opt(subObjBTy)));
4252 EXPECT_TRUE(clsExactBAATy.strictSubtypeOf(objcls(subObjBATy)));
4253 EXPECT_TRUE(objExactBAATy.strictSubtypeOf(opt(subObjBATy)));
4254 EXPECT_TRUE(clsExactBAATy.strictSubtypeOf(objcls(subObjBAATy)));
4255 EXPECT_TRUE(objExactBAATy.strictSubtypeOf(opt(subObjBAATy)));
4256 EXPECT_TRUE(objcls(objExactATy).couldBe(subClsATy));
4257 EXPECT_TRUE(objcls(objExactBAATy).couldBe(subClsBaseTy));
4258 EXPECT_TRUE(objExactBAATy.couldBe(opt(subObjBaseTy)));
4259 EXPECT_TRUE(objcls(objExactBAATy).couldBe(subClsBTy));
4260 EXPECT_TRUE(objExactBAATy.couldBe(opt(subObjBTy)));
4261 EXPECT_TRUE(clsExactBAATy.couldBe(objcls(subObjBATy)));
4262 EXPECT_TRUE(objExactBAATy.couldBe(opt(subObjBATy)));
4263 EXPECT_TRUE(clsExactBAATy.couldBe(objcls(subObjBAATy)));
4264 EXPECT_TRUE(objExactBAATy.couldBe(opt(subObjBAATy)));
4266 // a T<= is a subtype of itself but not a strict subtype
4267 // also a T<= is in a "could be" relationship with itself
4268 EXPECT_TRUE(objcls(subObjBaseTy).subtypeOf(subClsBaseTy));
4269 EXPECT_FALSE(objcls(subObjBaseTy).strictSubtypeOf(objcls(subObjBaseTy)));
4270 EXPECT_TRUE(objcls(subObjBAATy).subtypeOf(subClsBAATy));
4271 EXPECT_FALSE(subClsBAATy.strictSubtypeOf(objcls(subObjBAATy)));
4272 EXPECT_TRUE(subClsBAATy.couldBe(subClsBAATy));
4274 // a T<= type is in no subtype relationship with T=.
4275 // However a T<= is in a "could be" relationship with T=.
4276 EXPECT_FALSE(objcls(subObjATy).subtypeOf(clsExactATy));
4277 EXPECT_FALSE(objcls(subObjATy).strictSubtypeOf(clsExactATy));
4278 EXPECT_TRUE(clsExactATy.couldBe(objcls(subObjATy)));
4280 // Given 2 types A and B in no inheritance relationship then
4281 // A<= and B<= are in no subtype or "could be" relationship.
4282 // Same if one of the 2 types is an optional type
4283 EXPECT_FALSE(objcls(subObjATy).subtypeOf(clsExactBTy));
4284 EXPECT_FALSE(objcls(subObjATy).strictSubtypeOf(clsExactBTy));
4285 EXPECT_FALSE(subObjATy.subtypeOf(opt(objExactBTy)));
4286 EXPECT_FALSE(subObjATy.strictSubtypeOf(opt(objExactBTy)));
4287 EXPECT_FALSE(clsExactATy.couldBe(objcls(subObjBTy)));
4288 EXPECT_FALSE(objExactATy.couldBe(opt(subObjBTy)));
4289 EXPECT_FALSE(objcls(subObjBTy).subtypeOf(clsExactATy));
4290 EXPECT_FALSE(subObjBTy.subtypeOf(opt(objExactATy)));
4291 EXPECT_FALSE(objcls(subObjBTy).strictSubtypeOf(clsExactATy));
4292 EXPECT_FALSE(subObjBTy.strictSubtypeOf(opt(objExactATy)));
4293 EXPECT_FALSE(clsExactBTy.couldBe(objcls(subObjATy)));
4294 EXPECT_FALSE(objExactBTy.couldBe(opt(subObjATy)));
4296 // Given the hierarchy A <- B <- C where A is the base then:
4297 // C<= is a subtype and a strict subtype of B<=, ?B<=, A<= and ?A<=.
4298 // It is also in a "could be" relationship with all its ancestors
4299 // (including optional)
4300 EXPECT_TRUE(objcls(subObjBAATy).subtypeOf(subClsBaseTy));
4301 EXPECT_TRUE(subObjBAATy.subtypeOf(opt(subObjBaseTy)));
4302 EXPECT_TRUE(objcls(subObjBAATy).subtypeOf(subClsBTy));
4303 EXPECT_TRUE(subObjBAATy.subtypeOf(opt(subObjBTy)));
4304 EXPECT_TRUE(subClsBAATy.subtypeOf(objcls(subObjBATy)));
4305 EXPECT_TRUE(subObjBAATy.subtypeOf(opt(subObjBATy)));
4306 EXPECT_TRUE(objcls(subObjBAATy).strictSubtypeOf(subClsBaseTy));
4307 EXPECT_TRUE(subObjBAATy.strictSubtypeOf(opt(subObjBaseTy)));
4308 EXPECT_TRUE(objcls(subObjBAATy).strictSubtypeOf(subClsBTy));
4309 EXPECT_TRUE(subObjBAATy.strictSubtypeOf(opt(subObjBTy)));
4310 EXPECT_TRUE(subClsBAATy.strictSubtypeOf(objcls(subObjBATy)));
4311 EXPECT_TRUE(subObjBAATy.strictSubtypeOf(opt(subObjBATy)));
4312 EXPECT_TRUE(objcls(subObjBAATy).couldBe(subClsBaseTy));
4313 EXPECT_TRUE(subObjBAATy.couldBe(opt(subObjBaseTy)));
4314 EXPECT_TRUE(objcls(subObjBAATy).couldBe(subClsBTy));
4315 EXPECT_TRUE(subObjBAATy.couldBe(opt(subObjBTy)));
4316 EXPECT_TRUE(subClsBAATy.couldBe(objcls(subObjBATy)));
4317 EXPECT_TRUE(subObjBAATy.couldBe(opt(subObjBATy)));
4319 // Given the hierarchy A <- B <- C where A is the base then:
4320 // A<= is not in a subtype neither a strict subtype with B<=, ?B<=, A<=
4321 // ?A<=. However A<= is in a "could be" relationship with all its
4322 // children (including optional)
4323 EXPECT_FALSE(objcls(subObjBaseTy).subtypeOf(subClsATy));
4324 EXPECT_FALSE(subObjBaseTy.subtypeOf(opt(subObjATy)));
4325 EXPECT_FALSE(objcls(subObjBaseTy).subtypeOf(subClsBTy));
4326 EXPECT_FALSE(subObjBaseTy.subtypeOf(opt(subObjBTy)));
4327 EXPECT_FALSE(subClsBaseTy.subtypeOf(objcls(subObjAATy)));
4328 EXPECT_FALSE(subObjBaseTy.subtypeOf(opt(subObjAATy)));
4329 EXPECT_FALSE(subClsBaseTy.subtypeOf(objcls(subObjABTy)));
4330 EXPECT_FALSE(subObjBaseTy.subtypeOf(opt(subObjABTy)));
4331 EXPECT_FALSE(objcls(subObjBaseTy).subtypeOf(subClsBATy));
4332 EXPECT_FALSE(subObjBaseTy.subtypeOf(opt(subObjBATy)));
4333 EXPECT_FALSE(subClsBaseTy.subtypeOf(objcls(subObjBBTy)));
4334 EXPECT_FALSE(subObjBaseTy.subtypeOf(opt(subObjBBTy)));
4335 EXPECT_FALSE(subClsBaseTy.subtypeOf(objcls(subObjBAATy)));
4336 EXPECT_FALSE(subObjBaseTy.subtypeOf(opt(subObjBAATy)));
4337 EXPECT_FALSE(objcls(subObjBaseTy).strictSubtypeOf(subClsATy));
4338 EXPECT_FALSE(subObjBaseTy.strictSubtypeOf(opt(subObjATy)));
4339 EXPECT_FALSE(objcls(subObjBaseTy).strictSubtypeOf(subClsBTy));
4340 EXPECT_FALSE(subObjBaseTy.strictSubtypeOf(opt(subObjBTy)));
4341 EXPECT_FALSE(subClsBaseTy.strictSubtypeOf(objcls(subObjAATy)));
4342 EXPECT_FALSE(subObjBaseTy.strictSubtypeOf(opt(subObjAATy)));
4343 EXPECT_FALSE(subClsBaseTy.strictSubtypeOf(objcls(subObjABTy)));
4344 EXPECT_FALSE(subObjBaseTy.strictSubtypeOf(opt(subObjABTy)));
4345 EXPECT_FALSE(objcls(subObjBaseTy).strictSubtypeOf(subClsBATy));
4346 EXPECT_FALSE(subObjBaseTy.strictSubtypeOf(opt(subObjBATy)));
4347 EXPECT_FALSE(subClsBaseTy.strictSubtypeOf(objcls(subObjBBTy)));
4348 EXPECT_FALSE(subObjBaseTy.strictSubtypeOf(opt(subObjBBTy)));
4349 EXPECT_FALSE(subClsBaseTy.strictSubtypeOf(objcls(subObjBAATy)));
4350 EXPECT_FALSE(subObjBaseTy.strictSubtypeOf(opt(subObjBAATy)));
4351 EXPECT_TRUE(objcls(subObjBaseTy).couldBe(subClsATy));
4352 EXPECT_TRUE(subObjBaseTy.couldBe(opt(subObjATy)));
4353 EXPECT_TRUE(objcls(subObjBaseTy).couldBe(subClsBTy));
4354 EXPECT_TRUE(subObjBaseTy.couldBe(opt(subObjBTy)));
4355 EXPECT_TRUE(subClsBaseTy.couldBe(objcls(subObjAATy)));
4356 EXPECT_TRUE(subObjBaseTy.couldBe(opt(subObjAATy)));
4357 EXPECT_TRUE(subClsBaseTy.couldBe(objcls(subObjABTy)));
4358 EXPECT_TRUE(subObjBaseTy.couldBe(opt(subObjABTy)));
4359 EXPECT_TRUE(objcls(subObjBaseTy).couldBe(subClsBATy));
4360 EXPECT_TRUE(subObjBaseTy.couldBe(opt(subObjBATy)));
4361 EXPECT_TRUE(subClsBaseTy.couldBe(objcls(subObjBBTy)));
4362 EXPECT_TRUE(subObjBaseTy.couldBe(opt(subObjBBTy)));
4363 EXPECT_TRUE(subClsBaseTy.couldBe(objcls(subObjBAATy)));
4364 EXPECT_TRUE(subObjBaseTy.couldBe(opt(subObjBAATy)));
4366 // check union_of
4367 // union of subCls
4368 EXPECT_EQ(union_of(subClsATy, subClsBTy), subClsBaseTy);
4369 EXPECT_EQ(union_of(subClsAATy, subClsABTy), subClsATy);
4370 EXPECT_EQ(union_of(subClsATy, subClsBAATy), subClsBaseTy);
4371 EXPECT_EQ(union_of(subClsBAATy, subClsBTy), subClsBTy);
4372 EXPECT_EQ(union_of(subClsBAATy, subClsBBTy), subClsBTy);
4373 EXPECT_EQ(union_of(subClsAATy, subClsBaseTy), subClsBaseTy);
4374 EXPECT_EQ(union_of(subClsAATy, subClsTestClassTy), TCls);
4375 // union of subCls and clsExact mixed
4376 EXPECT_EQ(union_of(clsExactATy, subClsBTy), subClsBaseTy);
4377 EXPECT_EQ(union_of(subClsAATy, clsExactABTy), subClsATy);
4378 EXPECT_EQ(union_of(clsExactATy, subClsBAATy), subClsBaseTy);
4379 EXPECT_EQ(union_of(subClsBAATy, clsExactBTy), subClsBTy);
4380 EXPECT_EQ(union_of(clsExactBAATy, subClsBBTy), subClsBTy);
4381 EXPECT_EQ(union_of(subClsAATy, clsExactBaseTy), subClsBaseTy);
4382 EXPECT_EQ(union_of(clsExactAATy, subClsTestClassTy), TCls);
4383 // union of clsExact
4384 EXPECT_EQ(union_of(clsExactATy, clsExactBTy), subClsBaseTy);
4385 EXPECT_EQ(union_of(clsExactAATy, clsExactABTy), subClsATy);
4386 EXPECT_EQ(union_of(clsExactATy, clsExactBAATy), subClsBaseTy);
4387 EXPECT_EQ(union_of(clsExactBAATy, clsExactBTy), subClsBTy);
4388 EXPECT_EQ(union_of(clsExactBAATy, clsExactBBTy), subClsBTy);
4389 EXPECT_EQ(union_of(clsExactAATy, clsExactBaseTy), subClsBaseTy);
4390 EXPECT_EQ(union_of(clsExactAATy, subClsTestClassTy), TCls);
4391 // union of subObj
4392 EXPECT_EQ(union_of(subObjATy, subObjBTy), subObjBaseTy);
4393 EXPECT_EQ(union_of(subObjAATy, subObjABTy), subObjATy);
4394 EXPECT_EQ(union_of(subObjATy, subObjBAATy), subObjBaseTy);
4395 EXPECT_EQ(union_of(subObjBAATy, subObjBTy), subObjBTy);
4396 EXPECT_EQ(union_of(subObjBAATy, subObjBBTy), subObjBTy);
4397 EXPECT_EQ(union_of(subObjAATy, subObjBaseTy), subObjBaseTy);
4398 EXPECT_EQ(union_of(subObjAATy, subObjTestClassTy), TObj);
4399 // union of subObj and objExact mixed
4400 EXPECT_EQ(union_of(objExactATy, subObjBTy), subObjBaseTy);
4401 EXPECT_EQ(union_of(subObjAATy, objExactABTy), subObjATy);
4402 EXPECT_EQ(union_of(objExactATy, subObjBAATy), subObjBaseTy);
4403 EXPECT_EQ(union_of(subObjBAATy, objExactBTy), subObjBTy);
4404 EXPECT_EQ(union_of(objExactBAATy, subObjBBTy), subObjBTy);
4405 EXPECT_EQ(union_of(subObjAATy, objExactBaseTy), subObjBaseTy);
4406 EXPECT_EQ(union_of(objExactAATy, subObjTestClassTy), TObj);
4407 // union of objExact
4408 EXPECT_EQ(union_of(objExactATy, objExactBTy), subObjBaseTy);
4409 EXPECT_EQ(union_of(objExactAATy, objExactABTy), subObjATy);
4410 EXPECT_EQ(union_of(objExactATy, objExactBAATy), subObjBaseTy);
4411 EXPECT_EQ(union_of(objExactBAATy, objExactBTy), subObjBTy);
4412 EXPECT_EQ(union_of(objExactBAATy, objExactBBTy), subObjBTy);
4413 EXPECT_EQ(union_of(objExactAATy, objExactBaseTy), subObjBaseTy);
4414 EXPECT_EQ(union_of(objExactAATy, objExactTestClassTy), TObj);
4415 // optional sub obj
4416 EXPECT_EQ(union_of(opt(subObjATy), opt(subObjBTy)), opt(subObjBaseTy));
4417 EXPECT_EQ(union_of(subObjAATy, opt(subObjABTy)), opt(subObjATy));
4418 EXPECT_EQ(union_of(opt(subObjATy), subObjBAATy), opt(subObjBaseTy));
4419 EXPECT_EQ(union_of(opt(subObjBAATy), opt(subObjBTy)), opt(subObjBTy));
4420 EXPECT_EQ(union_of(opt(subObjBAATy), subObjBBTy), opt(subObjBTy));
4421 EXPECT_EQ(union_of(opt(subObjAATy), opt(subObjBaseTy)), opt(subObjBaseTy));
4422 EXPECT_EQ(union_of(subObjAATy, opt(subObjTestClassTy)), opt(TObj));
4423 // optional sub and exact obj mixed
4424 EXPECT_EQ(union_of(opt(objExactATy), subObjBTy), opt(subObjBaseTy));
4425 EXPECT_EQ(union_of(subObjAATy, opt(objExactABTy)), opt(subObjATy));
4426 EXPECT_EQ(union_of(opt(objExactATy), objExactBAATy), opt(subObjBaseTy));
4427 EXPECT_EQ(union_of(subObjBAATy, opt(objExactBTy)), opt(subObjBTy));
4428 EXPECT_EQ(union_of(opt(subObjBAATy), objExactBBTy), opt(subObjBTy));
4429 EXPECT_EQ(union_of(objExactAATy, opt(objExactBaseTy)), opt(subObjBaseTy));
4430 EXPECT_EQ(union_of(opt(subObjAATy), objExactTestClassTy), opt(TObj));
4433 TEST(Type, Interface) {
4434 auto const program = make_test_program();
4435 auto const unit = program->units.back().get();
4436 auto const func = [&]() -> php::Func* {
4437 for (auto& f : unit->funcs) {
4438 if (f->name->isame(s_test.get())) return f.get();
4440 return nullptr;
4441 }();
4442 EXPECT_TRUE(func != nullptr);
4444 auto const ctx = Context { unit, func };
4445 Index idx{program.get()};
4447 // load classes in hierarchy
4448 auto const clsIA = idx.resolve_class(ctx, s_IA.get());
4449 if (!clsIA) ADD_FAILURE();
4450 auto const clsIB = idx.resolve_class(ctx, s_IB.get());
4451 if (!clsIB) ADD_FAILURE();
4452 auto const clsIAA = idx.resolve_class(ctx, s_IAA.get());
4453 if (!clsIAA) ADD_FAILURE();
4454 auto const clsA = idx.resolve_class(ctx, s_A.get());
4455 if (!clsA) ADD_FAILURE();
4456 auto const clsAA = idx.resolve_class(ctx, s_AA.get());
4457 if (!clsAA) ADD_FAILURE();
4459 // make sometypes and objects
4460 auto const subObjIATy = subObj(*clsIA);
4461 auto const subClsIATy = subCls(*clsIA);
4462 auto const subObjIAATy = subObj(*clsIAA);
4463 auto const subClsIAATy = subCls(*clsIAA);
4464 auto const subObjIBTy = subObj(*clsIB);
4465 auto const subObjATy = subObj(*clsA);
4466 auto const clsExactATy = clsExact(*clsA);
4467 auto const subClsATy = subCls(*clsA);
4468 auto const subObjAATy = subObj(*clsAA);
4469 auto const subClsAATy = subCls(*clsAA);
4470 auto const exactObjATy = objExact(*clsA);
4471 auto const exactObjAATy = objExact(*clsAA);
4473 EXPECT_TRUE(subClsATy.subtypeOf(objcls(subObjIATy)));
4474 EXPECT_TRUE(subClsATy.couldBe(objcls(subObjIATy)));
4475 EXPECT_EQ(objcls(subObjATy), subClsIATy);
4476 EXPECT_TRUE(subClsAATy.subtypeOf(objcls(subObjIAATy)));
4477 EXPECT_TRUE(subClsAATy.couldBe(objcls(subObjIAATy)));
4478 EXPECT_EQ(objcls(subObjAATy), objcls(subObjIAATy));
4480 EXPECT_FALSE(subClsATy.subtypeOf(objcls(subObjIAATy)));
4481 EXPECT_FALSE(objcls(subObjATy).strictSubtypeOf(objcls(subObjIAATy)));
4483 EXPECT_EQ(intersection_of(subObjIAATy, subObjAATy), subObjAATy);
4484 EXPECT_EQ(intersection_of(subObjIAATy, exactObjAATy), exactObjAATy);
4485 EXPECT_EQ(intersection_of(subObjIAATy, exactObjATy), TBottom);
4486 EXPECT_EQ(intersection_of(subObjIAATy, subObjATy), exactObjAATy);
4487 EXPECT_EQ(intersection_of(subObjIAATy, subObjIBTy), TBottom);
4489 EXPECT_FALSE(clsExactATy.couldBe(objcls(subObjIAATy)));
4491 EXPECT_TRUE(union_of(opt(exactObjATy), opt(subObjIATy)) == opt(subObjIATy));
4492 // Since we have invariants in the index that types only improve, it is
4493 // important that the below union is more or equally refined than the
4494 // above union.
4495 EXPECT_TRUE(union_of(opt(exactObjATy), subObjIATy) == opt(subObjIATy));
4498 TEST(Type, InterfaceCanonicalization) {
4499 auto const program = make_test_program();
4500 auto const unit = program->units.back().get();
4501 auto const func = [&]() -> php::Func* {
4502 for (auto& f : unit->funcs) {
4503 if (f->name->isame(s_test.get())) return f.get();
4505 return nullptr;
4506 }();
4507 EXPECT_TRUE(func != nullptr);
4509 auto const ctx = Context { unit, func };
4510 Index idx{program.get()};
4512 auto const clsICanon1 = idx.resolve_class(ctx, s_ICanon1.get());
4513 if (!clsICanon1) ADD_FAILURE();
4514 auto const clsICanon2 = idx.resolve_class(ctx, s_ICanon2.get());
4515 if (!clsICanon2) ADD_FAILURE();
4516 auto const clsICanon3 = idx.resolve_class(ctx, s_ICanon3.get());
4517 if (!clsICanon3) ADD_FAILURE();
4518 auto const clsICanon4 = idx.resolve_class(ctx, s_ICanon4.get());
4519 if (!clsICanon4) ADD_FAILURE();
4520 auto const clsICanon5 = idx.resolve_class(ctx, s_ICanon5.get());
4521 if (!clsICanon5) ADD_FAILURE();
4522 auto const clsICanon6 = idx.resolve_class(ctx, s_ICanon6.get());
4523 if (!clsICanon6) ADD_FAILURE();
4524 auto const clsCanon3 = idx.resolve_class(ctx, s_Canon3.get());
4525 if (!clsCanon3) ADD_FAILURE();
4527 EXPECT_EQ(subObj(*clsICanon1), TBottom);
4528 EXPECT_EQ(objExact(*clsICanon1), make_specialized_exact_object(BObj, *clsICanon1));
4529 EXPECT_EQ(subCls(*clsICanon1), TBottom);
4530 EXPECT_EQ(clsExact(*clsICanon1), make_specialized_exact_class(BCls, *clsICanon1));
4532 EXPECT_EQ(subObj(*clsICanon2), TBottom);
4533 EXPECT_EQ(objExact(*clsICanon2), make_specialized_exact_object(BObj, *clsICanon2));
4534 EXPECT_EQ(subCls(*clsICanon2), TBottom);
4535 EXPECT_EQ(clsExact(*clsICanon2), make_specialized_exact_class(BCls, *clsICanon2));
4537 EXPECT_EQ(subObj(*clsICanon3), make_specialized_sub_object(BObj, *clsICanon3, false, false));
4538 EXPECT_EQ(objExact(*clsICanon3), make_specialized_exact_object(BObj, *clsICanon3));
4539 EXPECT_EQ(subCls(*clsICanon3), make_specialized_sub_class(BCls, *clsICanon3, false, false));
4540 EXPECT_EQ(clsExact(*clsICanon3), make_specialized_exact_class(BCls, *clsICanon3));
4542 EXPECT_EQ(subObj(*clsICanon4), make_specialized_sub_object(BObj, *clsICanon3, false, false));
4543 EXPECT_EQ(objExact(*clsICanon4), make_specialized_exact_object(BObj, *clsICanon4));
4544 EXPECT_EQ(subCls(*clsICanon4), make_specialized_sub_class(BCls, *clsICanon3, false, false));
4545 EXPECT_EQ(clsExact(*clsICanon4), make_specialized_exact_class(BCls, *clsICanon4));
4547 EXPECT_EQ(subObj(*clsICanon5), make_specialized_exact_object(BObj, *clsCanon3));
4548 EXPECT_EQ(objExact(*clsICanon5), make_specialized_exact_object(BObj, *clsICanon5));
4549 EXPECT_EQ(subCls(*clsICanon5), make_specialized_exact_class(BCls, *clsCanon3));
4550 EXPECT_EQ(clsExact(*clsICanon5), make_specialized_exact_class(BCls, *clsICanon5));
4552 EXPECT_EQ(subObj(*clsICanon6), make_specialized_exact_object(BObj, *clsCanon3));
4553 EXPECT_EQ(objExact(*clsICanon6), make_specialized_exact_object(BObj, *clsICanon6));
4554 EXPECT_EQ(subCls(*clsICanon6), make_specialized_exact_class(BCls, *clsCanon3));
4555 EXPECT_EQ(clsExact(*clsICanon6), make_specialized_exact_class(BCls, *clsICanon6));
4558 TEST(Type, WaitH) {
4559 auto const program = make_test_program();
4560 Index index { program.get() };
4562 auto const rcls = index.builtin_class(s_Awaitable.get());
4563 auto const twhobj = subObj(rcls);
4565 auto const& all = allCases(index);
4566 for (auto const& t : all) {
4567 if (!t.subtypeOf(BInitCell)) continue;
4568 auto const wh = wait_handle(index, t);
4569 if (t.strictSubtypeOf(BInitCell)) {
4570 EXPECT_TRUE(is_specialized_wait_handle(wh));
4571 } else {
4572 EXPECT_FALSE(is_specialized_wait_handle(wh));
4573 EXPECT_TRUE(is_specialized_obj(wh));
4574 EXPECT_EQ(wh, twhobj);
4576 EXPECT_TRUE(wh.couldBe(twhobj));
4577 EXPECT_TRUE(wh.subtypeOf(twhobj));
4578 EXPECT_TRUE(wh.subtypeOf(wait_handle(index, TInitCell)));
4581 // union_of(WaitH<A>, WaitH<B>) == WaitH<union_of(A, B)>
4582 for (auto const& p1 : predefined()) {
4583 for (auto const& p2 : predefined()) {
4584 auto const& t1 = p1.second;
4585 auto const& t2 = p2.second;
4586 if (!t1.subtypeOf(BInitCell) || !t2.subtypeOf(BInitCell)) continue;
4587 auto const u1 = union_of(t1, t2);
4588 auto const u2 = union_of(wait_handle(index, t1), wait_handle(index, t2));
4589 if (u1.strictSubtypeOf(BInitCell)) {
4590 EXPECT_TRUE(is_specialized_wait_handle(u2));
4591 EXPECT_EQ(wait_handle_inner(u2), u1);
4592 EXPECT_EQ(wait_handle(index, u1), u2);
4593 } else {
4594 EXPECT_FALSE(is_specialized_wait_handle(u2));
4595 EXPECT_TRUE(is_specialized_obj(u2));
4596 EXPECT_EQ(u2, twhobj);
4599 if (t1.subtypeOf(t2)) {
4600 EXPECT_TRUE(wait_handle(index, t1).subtypeOf(wait_handle(index, t2)));
4601 } else {
4602 EXPECT_FALSE(wait_handle(index, t1).subtypeOf(wait_handle(index, t2)));
4605 // Two wait handles can always be each other
4606 EXPECT_TRUE(wait_handle(index, t1).couldBe(wait_handle(index, t2)));
4607 auto const isect =
4608 intersection_of(wait_handle(index, t1), wait_handle(index, t2));
4609 EXPECT_FALSE(isect.is(BBottom));
4610 EXPECT_TRUE(isect.subtypeOf(wait_handle(index, t1)));
4611 EXPECT_TRUE(isect.subtypeOf(wait_handle(index, t2)));
4615 // union_of(?WaitH<A>, ?WaitH<B>) == ?WaitH<union_of(A, B)>
4616 for (auto const& p1 : predefined()) {
4617 for (auto const& p2 : predefined()) {
4618 auto const& t1 = p1.second;
4619 auto const& t2 = p2.second;
4620 if (t1.is(BBottom) || t2.is(BBottom)) continue;
4621 if (!t1.subtypeOf(BInitCell) || !t2.subtypeOf(BInitCell)) continue;
4622 auto const w1 = opt(wait_handle(index, t1));
4623 auto const w2 = opt(wait_handle(index, t2));
4624 auto const u1 = union_of(w1, w2);
4625 auto const u2 = opt(wait_handle(index, union_of(t1, t2)));
4626 EXPECT_EQ(u1, u2);
4630 // Some test cases with optional wait handles.
4631 auto const optWH = opt(wait_handle(index, ival(2)));
4632 EXPECT_TRUE(TInitNull.subtypeOf(optWH));
4633 EXPECT_TRUE(optWH.subtypeOf(BOptObj));
4634 EXPECT_TRUE(optWH.subtypeOf(opt(twhobj)));
4635 EXPECT_TRUE(wait_handle(index, ival(2)).subtypeOf(optWH));
4636 EXPECT_FALSE(optWH.subtypeOf(wait_handle(index, ival(2))));
4637 EXPECT_TRUE(optWH.couldBe(wait_handle(index, ival(2))));
4639 // union_of(WaitH<T>, Obj<=Awaitable) == Obj<=Awaitable
4640 for (auto const& t : all) {
4641 if (!t.subtypeOf(BInitCell)) continue;
4642 auto const u = union_of(wait_handle(index, t), twhobj);
4643 EXPECT_EQ(u, twhobj);
4646 for (auto const& t : all) {
4647 if (!t.subtypeOf(BInitCell)) continue;
4648 auto const u1 = union_of(wait_handle(index, t), TInitNull);
4649 auto const u2 = union_of(TInitNull, wait_handle(index, t));
4650 EXPECT_EQ(u1, u2);
4651 if (t.strictSubtypeOf(BInitCell)) {
4652 EXPECT_TRUE(is_specialized_wait_handle(u1));
4653 EXPECT_TRUE(is_specialized_wait_handle(u2));
4654 } else {
4655 EXPECT_FALSE(is_specialized_wait_handle(u1));
4656 EXPECT_FALSE(is_specialized_wait_handle(u2));
4657 EXPECT_EQ(u1, opt(twhobj));
4658 EXPECT_EQ(u2, opt(twhobj));
4662 for (auto const& t : all) {
4663 if (!t.subtypeOf(BInitCell)) continue;
4664 auto const wh = wait_handle(index, t);
4665 EXPECT_EQ(intersection_of(wh, twhobj), wh);
4668 EXPECT_EQ(
4669 intersection_of(wait_handle(index, TInt), wait_handle(index, TStr)),
4670 wait_handle(index, TBottom)
4672 EXPECT_TRUE(wait_handle(index, TInt).couldBe(wait_handle(index, TStr)));
4676 TEST(Type, FromHNIConstraint) {
4677 EXPECT_EQ(from_hni_constraint(makeStaticString("?HH\\resource")), TOptRes);
4678 EXPECT_EQ(from_hni_constraint(makeStaticString("HH\\resource")), TRes);
4679 EXPECT_EQ(from_hni_constraint(makeStaticString("HH\\bool")), TBool);
4680 EXPECT_EQ(from_hni_constraint(makeStaticString("?HH\\bool")), TOptBool);
4681 EXPECT_EQ(from_hni_constraint(makeStaticString("HH\\int")), TInt);
4682 EXPECT_EQ(from_hni_constraint(makeStaticString("HH\\float")), TDbl);
4683 EXPECT_EQ(from_hni_constraint(makeStaticString("?HH\\float")), TOptDbl);
4684 EXPECT_EQ(from_hni_constraint(makeStaticString("HH\\mixed")), TInitCell);
4685 EXPECT_EQ(from_hni_constraint(makeStaticString("HH\\arraykey")), TArrKey);
4686 EXPECT_EQ(from_hni_constraint(makeStaticString("?HH\\arraykey")), TOptArrKey);
4687 EXPECT_EQ(from_hni_constraint(makeStaticString("HH\\nonnull")), TNonNull);
4688 EXPECT_EQ(from_hni_constraint(makeStaticString("?HH\\nonnull")), TInitCell);
4690 // These are conservative, but we're testing them that way. If we
4691 // make the function better later we'll remove the tests.
4692 EXPECT_EQ(from_hni_constraint(makeStaticString("stdClass")), TCell);
4693 EXPECT_EQ(from_hni_constraint(makeStaticString("?stdClass")), TCell);
4694 EXPECT_EQ(from_hni_constraint(makeStaticString("fooooo")), TCell);
4695 EXPECT_EQ(from_hni_constraint(makeStaticString("")), TCell);
4698 TEST(Type, DictPacked1) {
4699 auto const a1 = dict_packed({ival(2), TSStr, TInt});
4700 auto const a2 = dict_packed({TInt, TStr, TInitCell});
4701 auto const s1 = sdict_packed({ival(2), TSStr, TInt});
4702 auto const s2 = sdict_packed({TInt, TSStr, TInitUnc});
4704 for (auto& a : { a1, s1, a2, s2 }) {
4705 EXPECT_TRUE(a.subtypeOf(BDict));
4706 EXPECT_TRUE(a.subtypeOf(a));
4707 EXPECT_EQ(a, a);
4710 // Subtype stuff.
4712 EXPECT_TRUE(a1.subtypeOf(BDict));
4713 EXPECT_FALSE(a1.subtypeOf(BSDict));
4715 EXPECT_TRUE(s1.subtypeOf(BDict));
4716 EXPECT_TRUE(s1.subtypeOf(BSDict));
4718 EXPECT_TRUE(a1.subtypeOf(a2));
4719 EXPECT_TRUE(s1.subtypeOf(s2));
4720 EXPECT_TRUE(s1.subtypeOf(a1));
4722 // Could be stuff.
4724 EXPECT_TRUE(s1.couldBe(a1));
4725 EXPECT_TRUE(s2.couldBe(a2));
4727 EXPECT_TRUE(a1.couldBe(a2));
4728 EXPECT_TRUE(a2.couldBe(a1));
4729 EXPECT_TRUE(s1.couldBe(a2));
4730 EXPECT_TRUE(s2.couldBe(a1));
4732 EXPECT_TRUE(s1.couldBe(s2));
4733 EXPECT_TRUE(s2.couldBe(s1));
4736 TEST(Type, OptDictPacked1) {
4737 auto const a1 = opt(dict_packed({ival(2), TSStr, TInt}));
4738 auto const a2 = opt(dict_packed({TInt, TStr, TInitCell}));
4739 auto const s1 = opt(sdict_packed({ival(2), TSStr, TInt}));
4740 auto const s2 = opt(sdict_packed({TInt, TSStr, TInitUnc}));
4742 for (auto& a : { a1, s1, a2, s2 }) {
4743 EXPECT_TRUE(a.subtypeOf(BOptDict));
4744 EXPECT_TRUE(a.subtypeOf(a));
4745 EXPECT_EQ(a, a);
4748 // Subtype stuff.
4750 EXPECT_TRUE(a1.subtypeOf(BOptDict));
4751 EXPECT_FALSE(a1.subtypeOf(BOptSDict));
4753 EXPECT_TRUE(s1.subtypeOf(BOptDict));
4754 EXPECT_TRUE(s1.subtypeOf(BOptSDict));
4756 EXPECT_TRUE(a1.subtypeOf(a2));
4757 EXPECT_TRUE(s1.subtypeOf(s2));
4758 EXPECT_TRUE(s1.subtypeOf(a1));
4760 // Could be stuff.
4762 EXPECT_TRUE(s1.couldBe(a1));
4763 EXPECT_TRUE(s2.couldBe(a2));
4765 EXPECT_TRUE(a1.couldBe(a2));
4766 EXPECT_TRUE(a2.couldBe(a1));
4767 EXPECT_TRUE(s1.couldBe(a2));
4768 EXPECT_TRUE(s2.couldBe(a1));
4770 EXPECT_TRUE(s1.couldBe(s2));
4771 EXPECT_TRUE(s2.couldBe(s1));
4774 TEST(Type, DictPacked2) {
4776 auto const a1 = dict_packed({TInt, TInt, TDbl});
4777 auto const a2 = dict_packed({TInt, TInt});
4778 EXPECT_FALSE(a1.subtypeOf(a2));
4779 EXPECT_FALSE(a1.couldBe(a2));
4783 auto const a1 = dict_packed({TInitCell, TInt});
4784 auto const a2 = dict_packed({TInt, TInt});
4785 EXPECT_TRUE(a1.couldBe(a2));
4786 EXPECT_TRUE(a2.subtypeOf(a1));
4789 auto const packedDict = static_dict(0, 42, 1, 23, 2, 12);
4792 auto const a1 = dict_packed({TInt, TInt, TInt});
4793 auto const s1 = sdict_packed({TInt, TInt, TInt});
4794 auto const s2 = dict_val(packedDict);
4795 EXPECT_TRUE(s2.subtypeOf(a1));
4796 EXPECT_TRUE(s2.subtypeOf(s1));
4797 EXPECT_TRUE(s2.couldBe(a1));
4798 EXPECT_TRUE(s2.couldBe(s1));
4802 auto const s1 = sdict_packed({ival(42), ival(23), ival(12)});
4803 auto const s2 = dict_val(packedDict);
4804 auto const s3 = sdict_packed({TInt});
4805 auto const a4 = sdict_packed({TInt});
4806 auto const a5 = dict_packed({ival(42), ival(23), ival(12)});
4807 EXPECT_TRUE(s2.subtypeOf(s1));
4808 EXPECT_NE(s1, s2);
4809 EXPECT_FALSE(s2.subtypeOf(s3));
4810 EXPECT_FALSE(s2.couldBe(s3));
4811 EXPECT_FALSE(s2.subtypeOf(s3));
4812 EXPECT_FALSE(s2.couldBe(s3));
4813 EXPECT_TRUE(s2.couldBe(s1));
4814 EXPECT_TRUE(s2.couldBe(a5));
4815 EXPECT_TRUE(s2.subtypeOf(a5));
4816 EXPECT_FALSE(a5.subtypeOf(s2));
4820 TEST(Type, DictPackedUnion) {
4822 auto const a1 = dict_packed({TInt, TDbl});
4823 auto const a2 = dict_packed({TDbl, TInt});
4824 EXPECT_EQ(union_of(a1, a2), dict_packed({TNum, TNum}));
4828 auto const s1 = sdict_packed({TInt, TDbl});
4829 auto const s2 = sdict_packed({TDbl, TInt});
4830 EXPECT_EQ(union_of(s1, s1), s1);
4831 EXPECT_EQ(union_of(s1, s2), sdict_packed({TNum, TNum}));
4835 auto const s1 = sdict_packed({TInt});
4836 auto const s2 = sdict_packed({TDbl, TDbl});
4837 EXPECT_EQ(union_of(s1, s2), sdict_packedn(TNum));
4840 auto const packedDict1 = static_dict(0, 42, 1, 23, 2, 12);
4841 auto const packedDict2 = static_dict(0, 42, 1, 23.0, 2, 12);
4844 auto const s1 = dict_val(packedDict1);
4845 auto const s2 = sdict_packed({TInt, TInt, TInt});
4846 auto const s3 = sdict_packed({TInt, TNum, TInt});
4847 EXPECT_EQ(union_of(s1, s2), s2);
4848 EXPECT_EQ(union_of(s1, s3), s3);
4852 auto const s1 = sdict_packed({TInt});
4853 auto const os1 = opt(s1);
4854 EXPECT_EQ(union_of(s1, TInitNull), os1);
4855 EXPECT_EQ(union_of(os1, s1), os1);
4856 EXPECT_EQ(union_of(TInitNull, s1), os1);
4857 EXPECT_EQ(union_of(os1, os1), os1);
4861 auto const s1 = sdict_packed({TInt});
4862 EXPECT_EQ(union_of(s1, TSDict), TSDict);
4866 auto const s1 = dict_val(packedDict1);
4867 auto const s2 = dict_val(packedDict2);
4868 EXPECT_EQ(
4869 loosen_mark_for_testing(union_of(s1, s2)),
4870 loosen_mark_for_testing(
4871 sdict_packed({ival(42), union_of(ival(23), TDbl), ival(12)})
4877 TEST(Type, DictPackedN) {
4878 auto const packedDict = static_dict(0, 42, 1, 23, 2, 12);
4879 auto const a1 = dict_val(packedDict);
4880 auto const a2 = sdict_packed({TInt, TInt});
4881 EXPECT_EQ(union_of(a1, a2), sdict_packedn(TInt));
4883 auto const s2 = sdict_packed({TInt, TInt});
4884 EXPECT_TRUE(s2.subtypeOf(sdict_packedn(TInt)));
4885 EXPECT_FALSE(s2.subtypeOf(sdict_packedn(TDbl)));
4886 EXPECT_TRUE(s2.subtypeOf(sdict_packedn(TNum)));
4887 EXPECT_TRUE(s2.subtypeOf(dict_packedn(TInt)));
4888 EXPECT_TRUE(s2.subtypeOf(opt(dict_packedn(TInt))));
4890 EXPECT_TRUE(s2.couldBe(dict_packedn(TInt)));
4891 EXPECT_TRUE(s2.couldBe(dict_packedn(TInitCell)));
4893 auto const sn1 = sdict_packedn(TInt);
4894 auto const sn2 = sdict_packedn(TInitNull);
4896 EXPECT_EQ(union_of(sn1, sn2), sdict_packedn(TOptInt));
4897 EXPECT_EQ(union_of(sn1, TInitNull), opt(sn1));
4898 EXPECT_EQ(union_of(TInitNull, sn1), opt(sn1));
4899 EXPECT_FALSE(sn2.couldBe(sn1));
4900 EXPECT_FALSE(sn1.couldBe(sn2));
4902 auto const sn3 = sdict_packedn(TInitUnc);
4903 EXPECT_TRUE(sn1.couldBe(sn3));
4904 EXPECT_TRUE(sn2.couldBe(sn3));
4905 EXPECT_TRUE(sn3.couldBe(sn1));
4906 EXPECT_TRUE(sn3.couldBe(sn2));
4908 EXPECT_TRUE(s2.couldBe(sn3));
4909 EXPECT_TRUE(s2.couldBe(sn1));
4910 EXPECT_FALSE(s2.couldBe(sn2));
4913 TEST(Type, DictStruct) {
4914 auto const test_map_a = MapElems{map_elem(s_test, ival(2))};
4915 auto const test_map_b = MapElems{map_elem(s_test, TInt)};
4916 auto const test_map_c = MapElems{map_elem(s_test, ival(2)),
4917 map_elem(s_A, TInt),
4918 map_elem(s_B, TDbl)};
4920 auto const ta = dict_map(test_map_a);
4921 auto const tb = dict_map(test_map_b);
4922 auto const tc = dict_map(test_map_c);
4924 EXPECT_FALSE(ta.subtypeOf(tc));
4925 EXPECT_FALSE(tc.subtypeOf(ta));
4926 EXPECT_TRUE(ta.subtypeOf(tb));
4927 EXPECT_FALSE(tb.subtypeOf(ta));
4928 EXPECT_TRUE(ta.couldBe(tb));
4929 EXPECT_TRUE(tb.couldBe(ta));
4930 EXPECT_FALSE(tc.couldBe(ta));
4931 EXPECT_FALSE(tc.couldBe(tb));
4933 EXPECT_TRUE(ta.subtypeOf(BDict));
4934 EXPECT_TRUE(tb.subtypeOf(BDict));
4935 EXPECT_TRUE(tc.subtypeOf(BDict));
4937 auto const sa = sdict_map(test_map_a);
4938 auto const sb = sdict_map(test_map_b);
4939 auto const sc = sdict_map(test_map_c);
4941 EXPECT_FALSE(sa.subtypeOf(sc));
4942 EXPECT_FALSE(sc.subtypeOf(sa));
4943 EXPECT_TRUE(sa.subtypeOf(sb));
4944 EXPECT_FALSE(sb.subtypeOf(sa));
4945 EXPECT_TRUE(sa.couldBe(sb));
4946 EXPECT_TRUE(sb.couldBe(sa));
4947 EXPECT_FALSE(sc.couldBe(sa));
4948 EXPECT_FALSE(sc.couldBe(sb));
4950 EXPECT_TRUE(sa.subtypeOf(BSDict));
4951 EXPECT_TRUE(sb.subtypeOf(BSDict));
4952 EXPECT_TRUE(sc.subtypeOf(BSDict));
4954 auto const testDict = static_dict(s_A.get(), s_B.get(), s_test.get(), 12);
4956 auto const test_map_d = MapElems{map_elem(s_A, sval(s_B)), map_elem(s_test, ival(12))};
4957 auto const sd = sdict_map(test_map_d);
4958 EXPECT_TRUE(dict_val(testDict).subtypeOf(sd));
4960 auto const test_map_e = MapElems{map_elem(s_A, TSStr), map_elem(s_test, TNum)};
4961 auto const se = sdict_map(test_map_e);
4962 EXPECT_TRUE(dict_val(testDict).subtypeOf(se));
4963 EXPECT_TRUE(se.couldBe(dict_val(testDict)));
4966 TEST(Type, DictMapN) {
4967 auto const test_map =
4968 dict_val(static_dict(s_A.get(), s_B.get(), s_test.get(), 12));
4969 EXPECT_TRUE(test_map != dict_n(TSStr, TInitUnc));
4970 EXPECT_TRUE(test_map.subtypeOf(dict_n(TSStr, TInitUnc)));
4971 EXPECT_TRUE(test_map.subtypeOf(sdict_n(TSStr, TInitUnc)));
4972 EXPECT_TRUE(sdict_packedn({TInt}).subtypeOf(dict_n(TInt, TInt)));
4973 EXPECT_TRUE(sdict_packed({TInt}).subtypeOf(dict_n(TInt, TInt)));
4975 auto const test_map_a = MapElems{map_elem(s_test, ival(2))};
4976 auto const tstruct = sdict_map(test_map_a);
4978 EXPECT_TRUE(tstruct.subtypeOf(dict_n(TSStr, ival(2))));
4979 EXPECT_TRUE(tstruct.subtypeOf(dict_n(TSStr, TInt)));
4980 EXPECT_TRUE(tstruct.subtypeOf(sdict_n(TSStr, TInt)));
4981 EXPECT_TRUE(tstruct.subtypeOf(dict_n(TStr, TInt)));
4983 EXPECT_TRUE(test_map.couldBe(dict_n(TSStr, TInitCell)));
4984 EXPECT_FALSE(test_map.couldBe(dict_n(TSStr, TStr)));
4985 EXPECT_FALSE(test_map.couldBe(dict_n(TSStr, TObj)));
4987 EXPECT_FALSE(test_map.couldBe(dict_val(staticEmptyDictArray())));
4988 EXPECT_FALSE(dict_n(TSStr, TInt).couldBe(dict_val(staticEmptyDictArray())));
4990 EXPECT_TRUE(sdict_packedn(TInt).couldBe(sdict_n(TInt, TInt)));
4991 EXPECT_FALSE(sdict_packedn(TInt).couldBe(dict_n(TInt, TObj)));
4993 EXPECT_TRUE(tstruct.couldBe(sdict_n(TSStr, TInt)));
4994 EXPECT_FALSE(tstruct.couldBe(dict_n(TSStr, TObj)));
4997 TEST(Type, DictEquivalentRepresentations) {
4999 auto const simple = dict_val(static_dict(0, 42, 1, 23, 2, 12));
5000 auto const bulky = sdict_packed({ival(42), ival(23), ival(12)});
5001 EXPECT_NE(simple, bulky);
5002 EXPECT_TRUE(simple.subtypeOf(bulky));
5006 auto const simple =
5007 dict_val(static_dict(s_A.get(), s_B.get(), s_test.get(), 12));
5009 auto const map = MapElems{map_elem(s_A, sval(s_B)), map_elem(s_test, ival(12))};
5010 auto const bulky = sdict_map(map);
5012 EXPECT_NE(simple, bulky);
5013 EXPECT_TRUE(simple.subtypeOf(bulky));
5017 TEST(Type, DictUnions) {
5018 auto const test_map_a = MapElems{map_elem(s_test, ival(2))};
5019 auto const tstruct = sdict_map(test_map_a);
5021 auto const test_map_b = MapElems{map_elem(s_test, TInt)};
5022 auto const tstruct2 = sdict_map(test_map_b);
5024 auto const test_map_c = MapElems{map_elem(s_A, TInt)};
5025 auto const tstruct3 = sdict_map(test_map_c);
5027 auto const test_map_d = MapElems{map_elem(s_A, TInt), map_elem(s_test, TDbl)};
5028 auto const tstruct4 = sdict_map(test_map_d);
5030 auto const packed_int = dict_packedn(TInt);
5032 EXPECT_EQ(union_of(tstruct, packed_int),
5033 dict_n(union_of(sval(s_test), TInt), TInt));
5034 EXPECT_EQ(union_of(tstruct, tstruct2), tstruct2);
5035 EXPECT_EQ(union_of(tstruct, tstruct3), sdict_n(TSStr, TInt));
5036 EXPECT_EQ(union_of(tstruct, tstruct4), sdict_n(TSStr, TNum));
5038 EXPECT_EQ(union_of(sdict_packed({TInt, TDbl, TDbl}), sdict_packedn(TDbl)),
5039 sdict_packedn(TNum));
5040 EXPECT_EQ(union_of(sdict_packed({TInt, TDbl}), tstruct),
5041 sdict_n(union_of(sval(s_test), TInt), TNum));
5043 EXPECT_EQ(union_of(dict_n(TInt, TTrue), dict_n(TStr, TFalse)),
5044 dict_n(TArrKey, TBool));
5046 auto const dict_val1 = dict_val(static_dict(0, 42, 1, 23, 2, 12));
5047 auto const dict_val2 = dict_val(static_dict(0, 1, 1, 2, 2, 3, 3, 4, 4, 5));
5048 EXPECT_EQ(
5049 loosen_mark_for_testing(union_of(dict_val1, dict_val2)),
5050 loosen_mark_for_testing(sdict_packedn(TInt))
5054 TEST(Type, DictIntersections) {
5055 auto const test_map_a = MapElems{map_elem(s_test, ival(2))};
5056 auto const tstruct = sdict_map(test_map_a);
5058 auto const test_map_b = MapElems{map_elem(s_test, TInt)};
5059 auto const tstruct2 = sdict_map(test_map_b);
5061 auto const test_map_c = MapElems{map_elem(s_A, TInt)};
5062 auto const tstruct3 = sdict_map(test_map_c);
5064 auto const test_map_d = MapElems{map_elem(s_A, TInt), map_elem(s_test, TDbl)};
5065 auto const tstruct4 = sdict_map(test_map_d);
5067 auto const test_map_e = MapElems{map_elem(s_A, TInt), map_elem(s_B, TDbl)};
5068 auto const tstruct5 = sdict_map(test_map_e);
5070 auto const test_map_f = MapElems{map_elem(s_A, TUncArrKey), map_elem(s_B, TInt)};
5071 auto const tstruct6 = sdict_map(test_map_f);
5073 auto const test_map_g = MapElems{map_elem(s_A, TSStr), map_elem(s_B, TUncArrKey)};
5074 auto const tstruct7 = sdict_map(test_map_g);
5076 auto const test_map_h = MapElems{map_elem(s_A, TSStr), map_elem(s_B, TInt)};
5077 auto const tstruct8 = sdict_map(test_map_h);
5079 auto const test_map_i = MapElems{map_elem(s_A, TStr), map_elem(s_B, TInt), map_elem(s_BB, TVec)};
5080 auto const tstruct9 = dict_map(test_map_i);
5082 auto const test_map_j = MapElems{map_elem(s_A, TSStr), map_elem(s_B, TInt), map_elem(s_BB, TSVec)};
5083 auto const tstruct10 = sdict_map(test_map_j);
5085 auto const test_map_k = MapElems{map_elem(s_A, TSStr), map_elem(s_B, TInt), map_elem(s_BB, TObj)};
5086 auto const tstruct11 = dict_map(test_map_k);
5088 auto const mapn_str_int = dict_n(TStr, TInt);
5090 EXPECT_EQ(intersection_of(tstruct, mapn_str_int), tstruct);
5091 EXPECT_EQ(intersection_of(tstruct2, mapn_str_int), tstruct2);
5092 EXPECT_EQ(intersection_of(tstruct3, mapn_str_int), tstruct3);
5093 EXPECT_EQ(intersection_of(tstruct4, mapn_str_int), TBottom);
5094 EXPECT_EQ(intersection_of(tstruct, tstruct2), tstruct);
5095 EXPECT_EQ(intersection_of(tstruct, tstruct3), TBottom);
5096 EXPECT_EQ(intersection_of(tstruct4, tstruct5), TBottom);
5097 EXPECT_EQ(intersection_of(tstruct6, tstruct7), tstruct8);
5098 EXPECT_EQ(intersection_of(tstruct8, tstruct), TBottom);
5100 EXPECT_EQ(intersection_of(sdict_packed({TNum, TDbl, TNum}),
5101 sdict_packedn(TDbl)),
5102 sdict_packed({TDbl, TDbl, TDbl}));
5103 EXPECT_EQ(intersection_of(sdict_packed({TNum, TDbl, TNum}),
5104 sdict_packed({TDbl, TNum, TInt})),
5105 sdict_packed({TDbl, TDbl, TInt}));
5106 EXPECT_EQ(intersection_of(TSDictN, dict_n(TArrKey, TInitCell)),
5107 sdict_n(TUncArrKey, TInitUnc));
5108 EXPECT_EQ(intersection_of(TSDictN, dict_n(TArrKey, TInitCell)),
5109 sdict_n(TUncArrKey, TInitUnc));
5110 EXPECT_EQ(intersection_of(tstruct9, TSDictN), tstruct10);
5111 EXPECT_EQ(intersection_of(TSDictN, dict_packed({TStr, TVec, TInt, TInitCell})),
5112 sdict_packed({TSStr, TSVec, TInt, TInitUnc}));
5113 EXPECT_EQ(intersection_of(dict_packedn(TStr), TSDictN), sdict_packedn(TSStr));
5114 EXPECT_EQ(intersection_of(TSDictN, dict_packedn(TObj)), TBottom);
5115 EXPECT_EQ(intersection_of(dict_packed({TStr, TInt, TObj}), TSDictN), TBottom);
5116 EXPECT_EQ(intersection_of(TSDictN, tstruct11), TBottom);
5117 EXPECT_EQ(
5118 intersection_of(dict_n(TArrKey, TObj), TSDictN),
5119 TBottom
5121 EXPECT_EQ(
5122 intersection_of(union_of(dict_n(TInt, TObj), TDictE),
5123 union_of(dict_packed({TInt, TObj}), TDictE)),
5124 TDictE
5126 EXPECT_EQ(
5127 intersection_of(opt(dict_n(TInt, TObj)), TUnc),
5128 TInitNull
5130 EXPECT_EQ(
5131 intersection_of(opt(dict_packedn(TObj)), TInitUnc),
5132 TInitNull
5134 EXPECT_EQ(
5135 intersection_of(union_of(dict_packed({TInt, TObj}), TDictE), TUnc),
5136 TSDictE
5138 EXPECT_EQ(
5139 intersection_of(opt(union_of(dict_packed({TInt, TObj}), TDictE)), TUnc),
5140 opt(TSDictE)
5144 TEST(Type, DictOfDict) {
5145 auto const t1 = dict_n(TSStr, dict_n(TInt, TSStr));
5146 auto const t2 = dict_n(TSStr, TDict);
5147 auto const t3 = dict_n(TSStr, dict_packedn(TSStr));
5148 auto const t4 = dict_n(TSStr, dict_n(TSStr, TSStr));
5149 EXPECT_TRUE(t1.subtypeOf(t2));
5150 EXPECT_TRUE(t1.couldBe(t3));
5151 EXPECT_FALSE(t1.subtypeOf(t3));
5152 EXPECT_TRUE(t3.subtypeOf(t1));
5153 EXPECT_TRUE(t3.subtypeOf(t2));
5154 EXPECT_FALSE(t1.couldBe(t4));
5155 EXPECT_FALSE(t4.couldBe(t3));
5156 EXPECT_TRUE(t4.subtypeOf(t2));
5159 TEST(Type, WideningAlreadyStable) {
5160 // A widening union on types that are already stable should not move
5161 // the type anywhere.
5162 auto const program = make_test_program();
5163 Index index { program.get() };
5165 auto const& all = allCases(index);
5166 for (auto const& t : all) {
5167 EXPECT_EQ(widening_union(t, t), t);
5170 auto deepPacked = svec({TInt});
5171 auto deepPackedN = svec_n(TInt);
5172 auto deepMap = sdict_map({map_elem(s_A, TInt)});
5173 auto deepMapN = sdict_n(TInt, TInt);
5174 for (size_t i = 0; i < 10; ++i) {
5175 deepPacked = widening_union(deepPacked, svec({deepPacked}));
5176 deepPackedN = widening_union(deepPackedN, svec_n(deepPackedN));
5177 deepMap = widening_union(deepMap, sdict_map({map_elem(s_A, deepMap)}, TSStr, deepMap));
5178 deepMapN = widening_union(deepMapN, sdict_n(TInt, deepMapN));
5180 EXPECT_EQ(deepPacked, widening_union(deepPacked, svec({deepPacked})));
5181 EXPECT_EQ(deepPackedN, widening_union(deepPackedN, svec_n(deepPackedN)));
5182 EXPECT_EQ(deepMap, widening_union(deepMap, sdict_map({map_elem(s_A, deepMap)}, TSStr, deepMap)));
5183 EXPECT_EQ(deepMapN, widening_union(deepMapN, sdict_n(TInt, deepMapN)));
5186 TEST(Type, EmptyDict) {
5188 auto const possible_e = union_of(dict_packedn(TInt), dict_empty());
5189 EXPECT_TRUE(possible_e.couldBe(dict_empty()));
5190 EXPECT_TRUE(possible_e.couldBe(dict_packedn(TInt)));
5191 EXPECT_EQ(array_like_elem(possible_e, ival(0)).first, TInt);
5195 auto const possible_e = union_of(dict_packed({TInt, TInt}), dict_empty());
5196 EXPECT_TRUE(possible_e.couldBe(dict_empty()));
5197 EXPECT_TRUE(possible_e.couldBe(dict_packed({TInt, TInt})));
5198 EXPECT_FALSE(possible_e.couldBe(dict_packed({TInt, TInt, TInt})));
5199 EXPECT_FALSE(possible_e.subtypeOf(dict_packedn(TInt)));
5200 EXPECT_EQ(array_like_elem(possible_e, ival(0)).first, TInt);
5201 EXPECT_EQ(array_like_elem(possible_e, ival(1)).first, TInt);
5205 auto const estat = union_of(sdict_packedn(TInt), dict_empty());
5206 EXPECT_TRUE(estat.couldBe(dict_empty()));
5207 EXPECT_TRUE(estat.couldBe(sdict_packedn(TInt)));
5208 EXPECT_FALSE(estat.subtypeOf(sdict_packedn(TInt)));
5209 EXPECT_FALSE(estat.subtypeOf(BSDictE));
5210 EXPECT_TRUE(estat.couldBe(BSDictE));
5213 EXPECT_EQ(
5214 loosen_mark_for_testing(array_like_newelem(dict_empty(), ival(142)).first),
5215 loosen_mark_for_testing(dict_packed({ival(142)}))
5219 TEST(Type, ArrKey) {
5220 EXPECT_TRUE(TInt.subtypeOf(BArrKey));
5221 EXPECT_TRUE(TStr.subtypeOf(BArrKey));
5222 EXPECT_TRUE(ival(0).subtypeOf(BArrKey));
5223 EXPECT_TRUE(sval(s_test).subtypeOf(BArrKey));
5224 EXPECT_TRUE(sval_nonstatic(s_test).subtypeOf(BArrKey));
5226 EXPECT_TRUE(TInt.subtypeOf(BUncArrKey));
5227 EXPECT_TRUE(TSStr.subtypeOf(BUncArrKey));
5228 EXPECT_TRUE(ival(0).subtypeOf(BUncArrKey));
5229 EXPECT_TRUE(sval(s_test).subtypeOf(BUncArrKey));
5231 EXPECT_TRUE(TArrKey.subtypeOf(BInitCell));
5232 EXPECT_TRUE(TUncArrKey.subtypeOf(BInitCell));
5233 EXPECT_TRUE(TOptArrKey.subtypeOf(BInitCell));
5234 EXPECT_TRUE(TOptUncArrKey.subtypeOf(BInitCell));
5236 EXPECT_TRUE(TUncArrKey.subtypeOf(BInitUnc));
5237 EXPECT_TRUE(TOptUncArrKey.subtypeOf(BInitUnc));
5239 EXPECT_EQ(union_of(TInt, TStr), TArrKey);
5240 EXPECT_EQ(union_of(TInt, TSStr), TUncArrKey);
5241 EXPECT_EQ(union_of(TArrKey, TInitNull), TOptArrKey);
5242 EXPECT_EQ(union_of(TUncArrKey, TInitNull), TOptUncArrKey);
5244 EXPECT_EQ(opt(TArrKey), TOptArrKey);
5245 EXPECT_EQ(opt(TUncArrKey), TOptUncArrKey);
5246 EXPECT_EQ(unopt(TOptArrKey), TArrKey);
5247 EXPECT_EQ(unopt(TOptUncArrKey), TUncArrKey);
5250 TEST(Type, LoosenStaticness) {
5251 auto const program = make_test_program();
5252 Index index{ program.get() };
5254 auto const& all = allCases(index);
5256 for (auto const& t : all) {
5257 if (!t.couldBe(BStr | BArrLike)) {
5258 EXPECT_EQ(loosen_staticness(t), t);
5261 if (!t.subtypeOf(BCell)) continue;
5262 auto const [obj, objRest] = split_obj(t);
5263 auto const [str, strRest] = split_string(objRest);
5264 auto const [arr, rest] = split_array_like(strRest);
5265 EXPECT_EQ(loosen_staticness(rest), rest);
5266 EXPECT_EQ(
5267 loosen_staticness(t),
5268 union_of(
5269 loosen_staticness(obj),
5270 loosen_staticness(str),
5271 loosen_staticness(arr),
5272 rest
5275 if (!t.is(BBottom)) {
5276 EXPECT_FALSE(loosen_staticness(t).subtypeOf(BSStr | BSArrLike));
5277 EXPECT_FALSE(loosen_staticness(t).subtypeOf(BCStr | BCArrLike));
5281 auto const test = [&] (const Type& a, const Type& b) {
5282 EXPECT_EQ(loosen_mark_for_testing(loosen_staticness(opt(a))),
5283 loosen_mark_for_testing(opt(b)));
5284 if (a.strictSubtypeOf(BInitCell)) {
5285 EXPECT_EQ(loosen_mark_for_testing(loosen_staticness(wait_handle(index, a))),
5286 loosen_mark_for_testing(wait_handle(index, b)));
5287 EXPECT_EQ(loosen_mark_for_testing(loosen_staticness(dict_packedn(a))),
5288 loosen_mark_for_testing(dict_packedn(b)));
5289 EXPECT_EQ(loosen_mark_for_testing(loosen_staticness(dict_packed({a}))),
5290 loosen_mark_for_testing(dict_packed({b})));
5291 EXPECT_EQ(loosen_mark_for_testing(loosen_staticness(dict_n(TSStr, a))),
5292 loosen_mark_for_testing(dict_n(TStr, b)));
5293 EXPECT_EQ(loosen_mark_for_testing(loosen_staticness(dict_map({map_elem(s_A, a)}, TInt, a))),
5294 loosen_mark_for_testing(dict_map({map_elem_nonstatic(s_A, b)}, TInt, b)));
5295 EXPECT_EQ(loosen_mark_for_testing(loosen_staticness(dict_map({map_elem(s_A, a)}, TSStr, a))),
5296 loosen_mark_for_testing(dict_map({map_elem_nonstatic(s_A, b)}, TStr, b)));
5297 EXPECT_EQ(loosen_mark_for_testing(loosen_staticness(dict_map({map_elem_counted(s_A, a)}, TSStr, a))),
5298 loosen_mark_for_testing(dict_map({map_elem_nonstatic(s_A, b)}, TStr, b)));
5300 if (a.strictSubtypeOf(BUnc)) {
5301 EXPECT_EQ(loosen_mark_for_testing(loosen_staticness(sdict_packedn(a))),
5302 loosen_mark_for_testing(dict_packedn(b)));
5303 EXPECT_EQ(loosen_mark_for_testing(loosen_staticness(sdict_packedn(a))),
5304 loosen_mark_for_testing(dict_packedn(b)));
5305 EXPECT_EQ(loosen_mark_for_testing(loosen_staticness(sdict_packed({a}))),
5306 loosen_mark_for_testing(dict_packed({b})));
5307 EXPECT_EQ(loosen_mark_for_testing(loosen_staticness(sdict_n(TSStr, a))),
5308 loosen_mark_for_testing(dict_n(TStr, b)));
5309 EXPECT_EQ(loosen_mark_for_testing(loosen_staticness(sdict_map({map_elem(s_A, a)}, TInt, a))),
5310 loosen_mark_for_testing(dict_map({map_elem_nonstatic(s_A, b)}, TInt, b)));
5311 EXPECT_EQ(loosen_mark_for_testing(loosen_staticness(sdict_map({map_elem(s_A, a)}, TSStr, a))),
5312 loosen_mark_for_testing(dict_map({map_elem_nonstatic(s_A, b)}, TStr, b)));
5316 for (auto const& t : all) {
5317 if (t.is(BBottom) || !t.subtypeOf(BInitCell)) continue;
5318 test(t, loosen_staticness(t));
5321 auto const test_map1 = MapElems{map_elem(s_A, TInt)};
5322 auto const test_map2 = MapElems{map_elem_nonstatic(s_A, TInt)};
5323 auto const test_map3 = MapElems{map_elem_counted(s_A, TInt)};
5324 std::vector<std::pair<Type, Type>> tests = {
5325 { TSStr, TStr },
5326 { TSVecE, TVecE },
5327 { TSVecN, TVecN },
5328 { TSVec, TVec },
5329 { TSDictE, TDictE },
5330 { TSDictN, TDictN },
5331 { TSDict, TDict },
5332 { TSVecE, TVecE },
5333 { TSVecN, TVecN },
5334 { TSVec, TVec },
5335 { TSDictE, TDictE },
5336 { TSDictN, TDictN },
5337 { TSDict, TDict },
5338 { TSKeysetE, TKeysetE },
5339 { TSKeysetN, TKeysetN },
5340 { TSKeyset, TKeyset },
5341 { TUncArrKey, TArrKey },
5342 { TUnc,
5343 Type{BInitNull|BArrLike|BArrKey|BBool|BCls|BDbl|BFunc|BLazyCls|BClsMeth|BUninit} },
5344 { TInitUnc,
5345 Type{BInitNull|BArrLike|BArrKey|BBool|BCls|BDbl|BFunc|BLazyCls|BClsMeth} },
5346 { ival(123), ival(123) },
5347 { sval(s_test), sval_nonstatic(s_test) },
5348 { sdict_packedn(TInt), dict_packedn(TInt) },
5349 { sdict_packed({TInt, TBool}), dict_packed({TInt, TBool}) },
5350 { sdict_n(TSStr, TInt), dict_n(TStr, TInt) },
5351 { sdict_n(TInt, TSDictN), dict_n(TInt, TDictN) },
5352 { sdict_map(test_map1), dict_map(test_map2) },
5353 { dict_map(test_map3), dict_map(test_map2) },
5354 { TClsMeth, TClsMeth },
5355 { TObj, TObj },
5356 { TRes, TRes },
5357 { TInitCell, TInitCell },
5358 { vec_n(Type{BInitCell & ~BCStr}), TVecN },
5359 { dict_n(TArrKey, Type{BInitCell & ~BCStr}), TDictN },
5360 { dict_n(Type{BInt|BSStr}, TInitCell), TDictN },
5361 { wait_handle(index, Type{BInitCell & ~BCStr}), wait_handle(index, TInitCell) },
5362 { vec_val(static_vec(s_A.get(), 123, s_B.get(), 456)),
5363 vec({sval_nonstatic(s_A), ival(123), sval_nonstatic(s_B), ival(456)}) },
5364 { sdict_map({map_elem(s_A, TSStr)}, TSStr, TSStr), dict_map({map_elem_nonstatic(s_A, TStr)}, TStr, TStr) },
5365 { dict_val(static_dict(s_A.get(), s_A.get(), s_B.get(), s_B.get())),
5366 dict_map({map_elem_nonstatic(s_A, sval_nonstatic(s_A)), map_elem_nonstatic(s_B, sval_nonstatic(s_B))}) },
5368 for (auto const& p : tests) {
5369 EXPECT_EQ(loosen_mark_for_testing(loosen_staticness(p.first)),
5370 loosen_mark_for_testing(p.second));
5371 test(p.first, p.second);
5375 TEST(Type, LoosenStringStaticness) {
5376 auto const program = make_test_program();
5377 Index index{ program.get() };
5379 auto const& all = allCases(index);
5380 for (auto const& t : all) {
5381 if (!t.couldBe(BStr)) {
5382 EXPECT_EQ(loosen_string_staticness(t), t);
5383 } else {
5384 EXPECT_FALSE(loosen_string_staticness(t).subtypeAmong(BSStr, BStr));
5385 EXPECT_FALSE(loosen_string_staticness(t).subtypeAmong(BCStr, BStr));
5388 if (!t.subtypeOf(BCell)) continue;
5389 auto const [str, rest] = split_string(t);
5390 EXPECT_EQ(loosen_string_staticness(rest), rest);
5391 EXPECT_EQ(
5392 loosen_string_staticness(t),
5393 union_of(loosen_string_staticness(str), rest)
5397 const std::vector<std::pair<Type, Type>> tests = {
5398 { TSStr, TStr },
5399 { TCStr, TStr },
5400 { TStr, TStr },
5401 { sval(s_A), sval_nonstatic(s_A) },
5402 { sval_counted(s_A), sval_nonstatic(s_A) },
5403 { sval_nonstatic(s_A), sval_nonstatic(s_A) },
5404 { TUncArrKey, TArrKey },
5405 { TArrKey, TArrKey },
5406 { union_of(TCStr,TInt), TArrKey },
5407 { TInt, TInt },
5408 { TObj, TObj },
5409 { TSArrLike, TSArrLike },
5410 { TCArrLike, TCArrLike },
5411 { TCell, TCell },
5412 { ival(1), ival(1) },
5413 { union_of(sval(s_A),TInt), union_of(sval_nonstatic(s_A),TInt) },
5414 { union_of(sval_counted(s_A),TInt), union_of(sval_nonstatic(s_A),TInt) },
5415 { union_of(sval_nonstatic(s_A),TInt), union_of(sval_nonstatic(s_A),TInt) },
5416 { union_of(ival(1),TSStr), union_of(ival(1),TStr) },
5417 { union_of(ival(1),TCStr), union_of(ival(1),TStr) },
5418 { union_of(ival(1),TStr), union_of(ival(1),TStr) },
5419 { TInitUnc, Type{(BInitUnc & ~BSStr) | BStr} },
5421 for (auto const& p : tests) {
5422 EXPECT_EQ(loosen_string_staticness(p.first), p.second);
5426 TEST(Type, LoosenArrayStaticness) {
5427 auto const program = make_test_program();
5428 Index index{ program.get() };
5430 auto const& all = allCases(index);
5432 for (auto const& t : all) {
5433 if (!t.couldBe(BArrLike)) {
5434 EXPECT_EQ(loosen_array_staticness(t), t);
5435 } else {
5436 EXPECT_FALSE(loosen_array_staticness(t).subtypeAmong(BSArrLike, BArrLike));
5437 EXPECT_FALSE(loosen_array_staticness(t).subtypeAmong(BCArrLike, BArrLike));
5440 if (!t.subtypeOf(BCell)) continue;
5441 auto const [arr, rest] = split_array_like(t);
5442 EXPECT_EQ(loosen_array_staticness(rest), rest);
5443 EXPECT_EQ(
5444 loosen_array_staticness(t),
5445 union_of(loosen_array_staticness(arr), rest)
5449 for (auto const& t : all) {
5450 if (t.is(BBottom) || !t.subtypeOf(BInitCell)) continue;
5452 EXPECT_EQ(loosen_array_staticness(opt(t)), opt(loosen_array_staticness(t)));
5454 if (t.strictSubtypeOf(BInitCell)) {
5455 EXPECT_EQ(loosen_array_staticness(wait_handle(index, t)), wait_handle(index, t));
5456 EXPECT_EQ(loosen_array_staticness(dict_packedn(t)), dict_packedn(t));
5457 EXPECT_EQ(loosen_array_staticness(dict_packed({t})), dict_packed({t}));
5458 EXPECT_EQ(loosen_array_staticness(dict_n(TSStr, t)), dict_n(TSStr, t));
5459 EXPECT_EQ(loosen_array_staticness(dict_map({map_elem(s_A, t)}, TSStr, t)),
5460 dict_map({map_elem(s_A, t)}, TSStr, t));
5461 EXPECT_EQ(loosen_array_staticness(dict_map({map_elem_counted(s_A, t)}, TSStr, t)),
5462 dict_map({map_elem_counted(s_A, t)}, TSStr, t));
5464 if (t.strictSubtypeOf(BUnc)) {
5465 EXPECT_EQ(loosen_array_staticness(sdict_packedn(t)), dict_packedn(t));
5466 EXPECT_EQ(loosen_array_staticness(sdict_packed({t})), dict_packed({t}));
5467 EXPECT_EQ(loosen_array_staticness(sdict_n(TSStr, t)), dict_n(TSStr, t));
5468 EXPECT_EQ(loosen_array_staticness(sdict_map({map_elem(s_A, t)}, TSStr, t)),
5469 dict_map({map_elem(s_A, t)}, TSStr, t));
5473 auto const test_map1 = MapElems{map_elem(s_A, TInt)};
5474 auto const test_map2 = MapElems{map_elem_nonstatic(s_A, TInt)};
5475 auto const test_map3 = MapElems{map_elem_counted(s_A, TInt)};
5476 std::vector<std::pair<Type, Type>> tests = {
5477 { TSStr, TSStr },
5478 { TCStr, TCStr},
5479 { TSVecE, TVecE },
5480 { TSVecN, TVecN },
5481 { TSVec, TVec },
5482 { TSDictE, TDictE },
5483 { TSDictN, TDictN },
5484 { TSDict, TDict },
5485 { TSVecE, TVecE },
5486 { TSVecN, TVecN },
5487 { TSVec, TVec },
5488 { TSDictE, TDictE },
5489 { TSDictN, TDictN },
5490 { TSDict, TDict },
5491 { TSKeysetE, TKeysetE },
5492 { TSKeysetN, TKeysetN },
5493 { TSKeyset, TKeyset },
5494 { TSArrLike, TArrLike },
5495 { TCArrLike, TArrLike },
5496 { TUncArrKey, TUncArrKey },
5497 { Type{BSVec|BInt}, Type{BVec|BInt} },
5498 { TUnc, Type{(BUnc & ~BSArrLike) | BArrLike} },
5499 { TInitUnc, Type{(BInitUnc & ~BSArrLike) | BArrLike} },
5500 { ival(123), ival(123) },
5501 { sval(s_test), sval(s_test) },
5502 { sdict_packedn(TInt), dict_packedn(TInt) },
5503 { sdict_packed({TInt, TBool}), dict_packed({TInt, TBool}) },
5504 { sdict_n(TSStr, TInt), dict_n(TSStr, TInt) },
5505 { sdict_n(TInt, TSDictN), dict_n(TInt, TSDictN) },
5506 { sdict_map(test_map1), dict_map(test_map1) },
5507 { dict_map(test_map2), dict_map(test_map2) },
5508 { dict_map(test_map3), dict_map(test_map3) },
5509 { TClsMeth, TClsMeth },
5510 { TObj, TObj },
5511 { TRes, TRes },
5512 { TInitCell, TInitCell },
5513 { vec_n(Type{BInitCell & ~BCArrLike}), vec_n(Type{BInitCell & ~BCArrLike}) },
5514 { dict_n(TArrKey, Type{BInitCell & ~BCArrLike}), dict_n(TArrKey, Type{BInitCell & ~BCArrLike}) },
5515 { wait_handle(index, Type{BInitCell & ~BCArrLike}), wait_handle(index, Type{BInitCell & ~BCArrLike}) },
5516 { vec_val(static_vec(s_A.get(), 123, s_B.get(), 456)),
5517 vec({sval(s_A), ival(123), sval(s_B), ival(456)}) },
5518 { sdict_map({map_elem(s_A, TSStr)}, TSStr, TSStr), dict_map({map_elem(s_A, TSStr)}, TSStr, TSStr) },
5519 { dict_val(static_dict(s_A.get(), s_A.get(), s_B.get(), s_B.get())),
5520 dict_map({map_elem(s_A, sval(s_A)), map_elem(s_B, sval(s_B))}) },
5522 for (auto const& p : tests) {
5523 EXPECT_EQ(loosen_mark_for_testing(loosen_array_staticness(p.first)),
5524 loosen_mark_for_testing(p.second));
5528 TEST(Type, Emptiness) {
5529 auto const program = make_test_program();
5530 Index index{ program.get() };
5532 std::vector<std::pair<Type, Emptiness>> tests{
5533 { TInitNull, Emptiness::Empty },
5534 { TUninit, Emptiness::Empty },
5535 { TFalse, Emptiness::Empty },
5536 { TVecE, Emptiness::Empty },
5537 { TSKeysetE, Emptiness::Empty },
5538 { TDictE, Emptiness::Empty },
5539 { TDict, Emptiness::Maybe },
5540 { TTrue, Emptiness::NonEmpty },
5541 { TVecN, Emptiness::NonEmpty },
5542 { TDictN, Emptiness::NonEmpty },
5543 { TArrLikeN, Emptiness::NonEmpty },
5544 { TArrLike, Emptiness::Maybe },
5545 { TObj, Emptiness::Maybe },
5546 { wait_handle(index, TInt), Emptiness::NonEmpty },
5547 { ival(0), Emptiness::Empty },
5548 { ival(1), Emptiness::NonEmpty },
5549 { opt(ival(0)), Emptiness::Empty },
5550 { opt(ival(1)), Emptiness::Maybe },
5551 { sempty(), Emptiness::Empty },
5552 { sval(s_A), Emptiness::NonEmpty },
5553 { lazyclsval(s_A), Emptiness::NonEmpty },
5554 { dval(3.14), Emptiness::NonEmpty },
5555 { dval(0), Emptiness::Empty },
5556 { TInitCell, Emptiness::Maybe },
5557 { TInt, Emptiness::Maybe },
5558 { TStr, Emptiness::Maybe },
5559 { TLazyCls, Emptiness::NonEmpty },
5560 { TCls, Emptiness::NonEmpty },
5561 { TDbl, Emptiness::Maybe }
5563 for (auto const& p : tests) {
5564 EXPECT_EQ(emptiness(p.first), p.second);
5568 TEST(Type, AssertNonEmptiness) {
5569 auto const program = make_test_program();
5570 Index index{ program.get() };
5572 auto const& all = allCases(index);
5573 for (auto const& t : all) {
5574 if (!t.subtypeOf(BCell)) continue;
5576 switch (emptiness(t)) {
5577 case Emptiness::Empty:
5578 EXPECT_EQ(assert_nonemptiness(t), TBottom);
5579 break;
5580 case Emptiness::Maybe:
5581 EXPECT_NE(emptiness(assert_nonemptiness(t)), Emptiness::Empty);
5582 break;
5583 case Emptiness::NonEmpty:
5584 EXPECT_EQ(assert_nonemptiness(t), t);
5585 break;
5588 if (!is_specialized_int(t) &&
5589 !is_specialized_double(t) &&
5590 !is_specialized_string(t) &&
5591 !t.couldBe(BNull | BFalse | BArrLikeE)) {
5592 EXPECT_EQ(assert_nonemptiness(t), t);
5594 EXPECT_FALSE(assert_nonemptiness(t).couldBe(BNull | BFalse | BArrLikeE));
5597 std::vector<std::pair<Type, Type>> tests{
5598 { TInitNull, TBottom },
5599 { TUninit, TBottom },
5600 { TFalse, TBottom },
5601 { TTrue, TTrue },
5602 { TBool, TTrue },
5603 { TVecE, TBottom },
5604 { TVec, TVecN },
5605 { TVecN, TVecN },
5606 { TDictE, TBottom },
5607 { TDictN, TDictN },
5608 { TDict, TDictN },
5609 { TArrLikeE, TBottom },
5610 { TArrLikeN, TArrLikeN },
5611 { TArrLike, TArrLikeN },
5612 { TObj, TObj },
5613 { Type{BInt|BFalse}, TInt },
5614 { wait_handle(index, TInt), wait_handle(index, TInt) },
5615 { ival(0), TBottom },
5616 { ival(1), ival(1) },
5617 { sempty(), TBottom },
5618 { sval(s_A), sval(s_A) },
5619 { lazyclsval(s_A), lazyclsval(s_A) },
5620 { dval(3.14), dval(3.14) },
5621 { dval(0), TBottom },
5622 { opt(ival(0)), TBottom },
5623 { opt(ival(1)), ival(1) },
5624 { TInitCell, Type{BInitCell & ~(BNull | BFalse | BArrLikeE)} },
5625 { TInt, TInt },
5626 { TStr, TStr },
5627 { TLazyCls, TLazyCls },
5628 { TDbl, TDbl },
5629 { union_of(ival(1),TStr), union_of(ival(1),TStr) },
5630 { union_of(ival(0),TStr), TArrKey },
5631 { union_of(ival(0),TDictE), TBottom }
5633 for (auto const& p : tests) {
5634 EXPECT_EQ(assert_nonemptiness(p.first), p.second);
5638 TEST(Type, AssertEmptiness) {
5639 auto const program = make_test_program();
5640 Index index{ program.get() };
5642 auto const& all = allCases(index);
5643 for (auto const& t : all) {
5644 if (!t.subtypeOf(BCell)) continue;
5646 switch (emptiness(t)) {
5647 case Emptiness::Empty:
5648 EXPECT_EQ(assert_emptiness(t), t);
5649 break;
5650 case Emptiness::Maybe:
5651 EXPECT_NE(emptiness(assert_emptiness(t)), Emptiness::NonEmpty);
5652 break;
5653 case Emptiness::NonEmpty:
5654 EXPECT_EQ(assert_emptiness(t), TBottom);
5655 break;
5658 EXPECT_EQ(t.couldBe(BInitNull), assert_emptiness(t).couldBe(BInitNull));
5659 EXPECT_FALSE(assert_emptiness(t).couldBe(BTrue | BArrLikeN));
5662 std::vector<std::pair<Type, Type>> tests{
5663 { TInitNull, TInitNull },
5664 { TUninit, TUninit },
5665 { TFalse, TFalse },
5666 { TTrue, TBottom },
5667 { TBool, TFalse },
5668 { TVecE, TVecE },
5669 { TVec, TVecE },
5670 { TVecN, TBottom },
5671 { TDictE, TDictE },
5672 { TDictN, TBottom },
5673 { TDict, TDictE },
5674 { TArrLikeE, TArrLikeE },
5675 { TArrLikeN, TBottom },
5676 { TArrLike, TArrLikeE },
5677 { TObj, TObj },
5678 { Type{BInt|BFalse}, union_of(ival(0),TFalse) },
5679 { Type{BInt|BTrue}, ival(0) },
5680 { Type{BInt|BBool}, union_of(ival(0),TFalse) },
5681 { wait_handle(index, TInt), TBottom },
5682 { ival(0), ival(0) },
5683 { ival(1), TBottom },
5684 { sempty(), sempty() },
5685 { sempty_nonstatic(), sempty_nonstatic() },
5686 { sval(s_A), TBottom },
5687 { lazyclsval(s_A), TBottom },
5688 { dval(3.14), TBottom },
5689 { dval(0), dval(0) },
5690 { opt(ival(0)), opt(ival(0)) },
5691 { opt(ival(1)), TInitNull },
5692 { TInt, ival(0) },
5693 { TStr, sempty_nonstatic() },
5694 { TSStr, sempty() },
5695 { TLazyCls, TBottom },
5696 { TDbl, dval(0) },
5697 { union_of(ival(1),TStr), TArrKey },
5698 { union_of(ival(0),TStr), union_of(TInt,sempty_nonstatic()) },
5699 { union_of(ival(0),TDictE), union_of(ival(0),TDictE) },
5700 { union_of(ival(0),TDictN), ival(0) },
5701 { dict_n(TArrKey, TInt), TBottom },
5702 { union_of(dict_n(TArrKey, TInt),TDictE), TDictE }
5704 for (auto const& p : tests) {
5705 EXPECT_EQ(assert_emptiness(p.first), p.second);
5709 TEST(Type, LoosenEmptiness) {
5710 auto const program = make_test_program();
5711 Index index{ program.get() };
5713 auto const clsA = index.resolve_class(Context{}, s_A.get());
5715 auto const& all = allCases(index);
5717 for (auto const& t : all) {
5718 if (!t.couldBe(BArrLike)) {
5719 EXPECT_EQ(loosen_emptiness(t), t);
5720 } else {
5721 EXPECT_FALSE(loosen_emptiness(t).subtypeAmong(BArrLikeE, BArrLike));
5722 EXPECT_FALSE(loosen_emptiness(t).subtypeAmong(BArrLikeN, BArrLike));
5725 if (!t.subtypeOf(BCell)) continue;
5726 auto const [arr, rest] = split_array_like(t);
5727 EXPECT_EQ(
5728 loosen_emptiness(t),
5729 union_of(loosen_emptiness(arr), loosen_emptiness(rest))
5733 auto const test_map = MapElems{map_elem(s_A, TInt)};
5734 std::vector<std::pair<Type, Type>> tests = {
5735 { TSVecE, TSVec },
5736 { TSVecN, TSVec },
5737 { TVecE, TVec },
5738 { TVecN, TVec },
5739 { TSDictE, TSDict },
5740 { TSDictN, TSDict },
5741 { TDictE, TDict },
5742 { TDictN, TDict },
5743 { TSKeysetE, TSKeyset },
5744 { TSKeysetN, TSKeyset },
5745 { TKeysetE, TKeyset },
5746 { TKeysetN, TKeyset },
5747 { TSVecE, TSVec },
5748 { TSVecN, TSVec },
5749 { TVecE, TVec },
5750 { TVecN, TVec },
5751 { TSDictE, TSDict },
5752 { TSDictN, TSDict },
5753 { TDictE, TDict },
5754 { TDictN, TDict },
5755 { dict_packedn(TInt), union_of(TDictE, dict_packedn(TInt)) },
5756 { dict_packed({TInt, TBool}), union_of(TDictE, dict_packed({TInt, TBool})) },
5757 { dict_n(TStr, TInt), union_of(TDictE, dict_n(TStr, TInt)) },
5758 { dict_map(test_map), union_of(TDictE, dict_map(test_map)) },
5759 { TSArrLikeE, TSArrLike },
5760 { TSArrLikeN, TSArrLike },
5761 { TArrLikeE, TArrLike },
5762 { TArrLikeN, TArrLike },
5763 { union_of(make_specialized_exact_object(BObj, *clsA), TSDictE),
5764 union_of(TObj, TSDict) },
5766 for (auto const& p : tests) {
5767 EXPECT_EQ(loosen_mark_for_testing(loosen_emptiness(p.first)),
5768 loosen_mark_for_testing(p.second));
5769 EXPECT_EQ(loosen_mark_for_testing(loosen_emptiness(opt(p.first))),
5770 loosen_mark_for_testing(opt(p.second)));
5774 TEST(Type, LoosenValues) {
5775 auto const program = make_test_program();
5776 auto const unit = program->units.back().get();
5777 auto const func = [&]() -> php::Func* {
5778 for (auto& f : unit->funcs) {
5779 if (f->name->isame(s_test.get())) return f.get();
5781 return nullptr;
5782 }();
5783 EXPECT_TRUE(func != nullptr);
5785 auto const ctx = Context { unit, func };
5786 Index index{ program.get() };
5788 auto const& all = allCases(index);
5790 for (auto const& t : all) {
5791 if (t.couldBe(BBool)) {
5792 EXPECT_FALSE(loosen_values(t).subtypeAmong(BFalse, BBool));
5793 EXPECT_FALSE(loosen_values(t).subtypeAmong(BTrue, BBool));
5794 EXPECT_EQ(get_bits(t) & ~BBool, get_bits(loosen_values(t)) & ~BBool);
5795 } else {
5796 EXPECT_EQ(get_bits(t), get_bits(loosen_values(t)));
5799 if (is_specialized_string(t) ||
5800 is_specialized_int(t) ||
5801 is_specialized_double(t) ||
5802 is_specialized_lazycls(t) ||
5803 is_specialized_array_like(t)) {
5804 EXPECT_FALSE(loosen_values(t).hasData());
5805 } else if (!t.couldBe(BBool)) {
5806 EXPECT_EQ(loosen_values(t), t);
5809 EXPECT_TRUE(t.subtypeOf(loosen_values(t)));
5810 EXPECT_FALSE(loosen_values(t).strictSubtypeOf(t));
5813 EXPECT_TRUE(loosen_values(TTrue) == TBool);
5814 EXPECT_TRUE(loosen_values(TFalse) == TBool);
5815 EXPECT_TRUE(loosen_values(TOptTrue) == TOptBool);
5816 EXPECT_TRUE(loosen_values(TOptFalse) == TOptBool);
5818 auto const test_map = MapElems{map_elem(s_A, TInt)};
5819 std::vector<std::pair<Type, Type>> tests = {
5820 { ival(123), TInt },
5821 { dval(3.14), TDbl },
5822 { sval(s_test), TSStr },
5823 { sval_nonstatic(s_test), TStr },
5824 { lazyclsval(s_test), TLazyCls },
5825 { dict_val(static_dict(0, 42, 1, 23, 2, 12)), TSDictN },
5826 { dict_packedn(TInt), TDictN },
5827 { dict_packed({TInt, TBool}), TDictN },
5828 { dict_n(TStr, TInt), TDictN },
5829 { dict_map(test_map), TDictN },
5830 { Type{BFalse|BInt}, Type{BBool|BInt} },
5831 { union_of(ival(123),TTrue), Type{BInt|BBool} },
5833 for (auto const& p : tests) {
5834 EXPECT_EQ(loosen_mark_for_testing(loosen_values(p.first)), p.second);
5835 EXPECT_EQ(loosen_mark_for_testing(loosen_values(opt(p.first))), opt(p.second));
5838 auto const cls = index.resolve_class(ctx, s_TestClass.get());
5839 EXPECT_TRUE(!!cls);
5841 EXPECT_TRUE(loosen_values(objExact(*cls)) == objExact(*cls));
5842 EXPECT_TRUE(loosen_values(subObj(*cls)) == subObj(*cls));
5843 EXPECT_TRUE(loosen_values(clsExact(*cls)) == clsExact(*cls));
5844 EXPECT_TRUE(loosen_values(subCls(*cls)) == subCls(*cls));
5846 EXPECT_TRUE(loosen_values(opt(objExact(*cls))) == opt(objExact(*cls)));
5847 EXPECT_TRUE(loosen_values(opt(subObj(*cls))) == opt(subObj(*cls)));
5850 TEST(Type, LoosenArrayValues) {
5851 auto const program = make_test_program();
5852 Index index{ program.get() };
5854 auto const& all = allCases(index);
5855 for (auto const& t : all) {
5856 EXPECT_EQ(get_bits(t), get_bits(loosen_array_values(t)));
5857 if (!is_specialized_array_like(t)) {
5858 EXPECT_EQ(loosen_array_values(t), t);
5860 EXPECT_FALSE(is_specialized_array_like(loosen_array_values(t)));
5861 EXPECT_TRUE(t.subtypeOf(loosen_array_values(t)));
5862 EXPECT_FALSE(loosen_array_values(t).strictSubtypeOf(t));
5866 TEST(Type, LoosenStringValues) {
5867 auto const program = make_test_program();
5868 Index index{ program.get() };
5870 auto const& all = allCases(index);
5871 for (auto const& t : all) {
5872 EXPECT_EQ(get_bits(t), get_bits(loosen_string_values(t)));
5873 if (!is_specialized_string(t)) {
5874 EXPECT_EQ(loosen_string_values(t), t);
5876 EXPECT_FALSE(is_specialized_string(loosen_string_values(t)));
5877 EXPECT_TRUE(t.subtypeOf(loosen_string_values(t)));
5878 EXPECT_FALSE(loosen_string_values(t).strictSubtypeOf(t));
5882 TEST(Type, AddNonEmptiness) {
5883 auto const program = make_test_program();
5884 Index index{ program.get() };
5886 auto const& all = allCases(index);
5887 for (auto const& t : all) {
5888 if (!t.couldBe(BArrLikeE)) {
5889 EXPECT_EQ(add_nonemptiness(t), t);
5890 } else {
5891 EXPECT_EQ(get_bits(t) & ~BArrLike,
5892 get_bits(add_nonemptiness(t)) & ~BArrLike);
5893 EXPECT_FALSE(add_nonemptiness(t).subtypeAmong(BArrLikeE, BArrLike));
5894 EXPECT_TRUE(add_nonemptiness(t).couldBe(BArrLikeN));
5895 EXPECT_TRUE(t.subtypeOf(add_nonemptiness(t)));
5898 EXPECT_EQ(t.hasData(), add_nonemptiness(t).hasData());
5900 if (!t.subtypeOf(BCell)) continue;
5901 auto const [arr, rest] = split_array_like(t);
5902 EXPECT_EQ(
5903 add_nonemptiness(t),
5904 union_of(add_nonemptiness(arr), add_nonemptiness(rest))
5908 auto const test_map = MapElems{map_elem(s_A, TInt)};
5909 std::vector<std::pair<Type, Type>> tests = {
5910 { TVecE, TVec },
5911 { TSVecE, TSVec },
5912 { TVecN, TVecN },
5913 { TSVecN, TSVecN },
5914 { TDictE, TDict },
5915 { TSDictE, TSDict },
5916 { TDictN, TDictN },
5917 { TSDictN, TSDictN },
5918 { TKeysetE, TKeyset },
5919 { TSKeysetE, TSKeyset },
5920 { TKeysetN, TKeysetN },
5921 { TSKeysetN, TSKeysetN },
5922 { TVecE, TVec },
5923 { TSVecE, TSVec },
5924 { TVecN, TVecN },
5925 { TSVecN, TSVecN },
5926 { TDictE, TDict },
5927 { TSDictE, TSDict },
5928 { TDictN, TDictN },
5929 { TSDictN, TSDictN },
5930 { TSArrLikeE, TSArrLike },
5931 { TArrLikeE, TArrLike },
5932 { TSArrLikeN, TSArrLikeN },
5933 { TArrLikeN, TArrLikeN },
5934 { dict_packedn(TInt), dict_packedn(TInt) },
5935 { dict_packed({TInt, TBool}), dict_packed({TInt, TBool}) },
5936 { dict_n(TStr, TInt), dict_n(TStr, TInt) },
5937 { dict_map(test_map), dict_map(test_map) },
5938 { vec_val(static_vec(s_A.get(), 123, s_B.get(), 456)),
5939 vec_val(static_vec(s_A.get(), 123, s_B.get(), 456)) },
5940 { TInitCell, TInitCell },
5941 { TObj, TObj },
5942 { Type{BVecE|BInt}, Type{BVec|BInt} },
5943 { Type{BVecN|BInt}, Type{BVecN|BInt} },
5945 for (auto const& p : tests) {
5946 EXPECT_EQ(add_nonemptiness(p.first), p.second);
5947 EXPECT_EQ(add_nonemptiness(opt(p.first)), opt(p.second));
5951 TEST(Type, LoosenVecOrDict) {
5952 auto const program = make_test_program();
5953 Index index{ program.get() };
5955 auto const& all = allCases(index);
5956 for (auto const& t : all) {
5957 if (!t.couldBe(BKVish)) {
5958 EXPECT_EQ(loosen_vec_or_dict(t), t);
5959 } else {
5960 EXPECT_EQ(get_bits(t) & ~BArrLike,
5961 get_bits(loosen_vec_or_dict(t)) & ~BArrLike);
5962 EXPECT_TRUE(t.subtypeOf(loosen_vec_or_dict(t)));
5965 if (!t.couldBe(BKeysetN)) {
5966 EXPECT_FALSE(is_specialized_array_like(loosen_vec_or_dict(t)));
5969 if (!t.subtypeOf(BCell)) continue;
5970 auto const [arr, rest] = split_array_like(t);
5971 EXPECT_EQ(
5972 loosen_vec_or_dict(t),
5973 union_of(loosen_vec_or_dict(arr), loosen_vec_or_dict(rest))
5977 auto const vecOrDict = union_of(TVec, TDict);
5978 std::vector<std::pair<Type, Type>> tests = {
5979 { TSVecE, vecOrDict },
5980 { TSVecN, vecOrDict },
5981 { TVecE, vecOrDict },
5982 { TVecN, vecOrDict },
5983 { TSVec, vecOrDict },
5984 { TVec, vecOrDict },
5985 { TSDictE, vecOrDict },
5986 { TSDictN, vecOrDict },
5987 { TDictE, vecOrDict },
5988 { TDictN, vecOrDict },
5989 { TSDict, vecOrDict },
5990 { TDict, vecOrDict },
5991 { TSKeysetE, TSKeysetE },
5992 { TSKeysetN, TSKeysetN },
5993 { TKeysetE, TKeysetE },
5994 { TKeysetN, TKeysetN },
5995 { TSKeyset, TSKeyset },
5996 { TKeyset, TKeyset },
5997 { TSArrLikeE, union_of(vecOrDict, TSKeysetE) },
5998 { TSArrLikeN, union_of(vecOrDict, TSKeysetN) },
5999 { TArrLikeE, union_of(vecOrDict, TKeysetE) },
6000 { TArrLikeN, union_of(vecOrDict, TKeysetN) },
6001 { TSArrLike, union_of(vecOrDict, TSKeyset) },
6002 { TArrLike, TArrLike },
6003 { TInitCell, TInitCell },
6004 { TObj, TObj },
6005 { TInt, TInt },
6006 { ival(123), ival(123) },
6007 { dict_packedn(TInt), vecOrDict },
6008 { dict_packed({TInt, TBool}), vecOrDict },
6009 { dict_n(TStr, TInt), vecOrDict },
6010 { dict_map({map_elem(s_A, TInt)}), vecOrDict },
6011 { vec_val(static_vec(s_A.get(), 123, s_B.get(), 456)), vecOrDict },
6012 { Type{BVecE|BInt}, union_of(vecOrDict, TInt) },
6013 { Type{BVecN|BInt}, union_of(vecOrDict, TInt) },
6015 for (auto const& p : tests) {
6016 EXPECT_EQ(loosen_vec_or_dict(p.first), p.second);
6017 EXPECT_EQ(loosen_vec_or_dict(opt(p.first)), opt(p.second));
6021 TEST(Type, Scalarize) {
6022 auto const program = make_test_program();
6023 Index index{ program.get() };
6025 auto const& all = allCases(index);
6026 for (auto const& t : all) {
6027 if (!is_scalar(t)) continue;
6028 EXPECT_EQ(scalarize(t), from_cell(*tv(t)));
6029 EXPECT_TRUE(scalarize(t).subtypeOf(BUnc));
6030 EXPECT_EQ(scalarize(t).hasData(), t.hasData());
6031 if (!t.hasData() && !t.subtypeOf(BArrLikeE)) {
6032 EXPECT_EQ(scalarize(t), t);
6034 if (is_specialized_int(t) || is_specialized_double(t) || is_specialized_lazycls(t)) {
6035 EXPECT_EQ(scalarize(t), t);
6037 if (is_specialized_string(t)) {
6038 EXPECT_TRUE(scalarize(t).subtypeOf(BSStr));
6040 if (is_specialized_array_like(t)) {
6041 EXPECT_TRUE(scalarize(t).subtypeOf(BSArrLikeN));
6045 std::vector<std::pair<Type, Type>> tests = {
6046 { TUninit, TUninit },
6047 { TInitNull, TInitNull },
6048 { TFalse, TFalse },
6049 { TTrue, TTrue },
6050 { TSVecE, TSVecE },
6051 { TVecE, TSVecE },
6052 { TSDictE, TSDictE },
6053 { TDictE, TSDictE },
6054 { TSKeysetE, TSKeysetE },
6055 { TKeysetE, TSKeysetE },
6056 { ival(123), ival(123) },
6057 { sval(s_A), sval(s_A) },
6058 { sval_nonstatic(s_A), sval(s_A) },
6059 { dval(3.14), dval(3.14) },
6060 { make_specialized_arrval(BSVecN, static_vec(100, 200)),
6061 make_specialized_arrval(BSVecN, static_vec(100, 200)) },
6062 { make_specialized_arrval(BSDictN, static_dict(s_A.get(), 100, s_B.get(), 200)),
6063 make_specialized_arrval(BSDictN, static_dict(s_A.get(), 100, s_B.get(), 200)) },
6064 { make_specialized_arrpacked(BVecN, {sval_nonstatic(s_A)}),
6065 make_specialized_arrval(BSVecN, static_vec(s_A.get())) },
6066 { make_specialized_arrpacked(BDictN, {sval_nonstatic(s_A)}),
6067 make_specialized_arrval(BSDictN, static_dict(0, s_A.get())) },
6068 { make_specialized_arrmap(BDictN, {map_elem_nonstatic(s_A, sval_nonstatic(s_B))}),
6069 make_specialized_arrval(BSDictN, static_dict(s_A.get(), s_B.get())) },
6071 for (auto const& p : tests) {
6072 EXPECT_EQ(scalarize(make_unmarked(p.first)), make_unmarked(p.second));
6076 TEST(Type, StrValues) {
6077 auto const t1 = sval(s_test);
6078 auto const t2 = sval_nonstatic(s_test);
6079 auto const t3 = sval(s_A);
6080 auto const t4 = sval_nonstatic(s_test);
6081 auto const t5 = sval_nonstatic(s_A);
6083 EXPECT_TRUE(t1.subtypeOf(t2));
6084 EXPECT_TRUE(t1.subtypeOf(TSStr));
6085 EXPECT_TRUE(t1.subtypeOf(TStr));
6086 EXPECT_FALSE(t1.subtypeOf(t3));
6088 EXPECT_FALSE(t2.subtypeOf(t1));
6089 EXPECT_FALSE(t2.subtypeOf(TSStr));
6090 EXPECT_TRUE(t2.subtypeOf(TStr));
6091 EXPECT_FALSE(t2.subtypeOf(t3));
6092 EXPECT_TRUE(t2.subtypeOf(t4));
6093 EXPECT_FALSE(t2.subtypeOf(t5));
6095 EXPECT_FALSE(TStr.subtypeOf(t1));
6096 EXPECT_FALSE(TSStr.subtypeOf(t2));
6097 EXPECT_FALSE(TStr.subtypeOf(t2));
6098 EXPECT_FALSE(TSStr.subtypeOf(t2));
6099 EXPECT_FALSE(t2.subtypeOf(t1));
6100 EXPECT_FALSE(t3.subtypeOf(t2));
6101 EXPECT_TRUE(t4.subtypeOf(t2));
6102 EXPECT_FALSE(t5.subtypeOf(t2));
6104 EXPECT_TRUE(t1.couldBe(t2));
6105 EXPECT_FALSE(t1.couldBe(t3));
6106 EXPECT_TRUE(t1.couldBe(TStr));
6107 EXPECT_TRUE(t1.couldBe(TSStr));
6109 EXPECT_TRUE(t2.couldBe(t1));
6110 EXPECT_FALSE(t2.couldBe(t3));
6111 EXPECT_TRUE(t2.couldBe(t4));
6112 EXPECT_FALSE(t2.couldBe(t5));
6113 EXPECT_TRUE(t2.couldBe(TStr));
6114 EXPECT_TRUE(t2.couldBe(TSStr));
6116 EXPECT_TRUE(TSStr.couldBe(t1));
6117 EXPECT_TRUE(TStr.couldBe(t1));
6118 EXPECT_TRUE(TSStr.couldBe(t2));
6119 EXPECT_TRUE(TStr.couldBe(t2));
6120 EXPECT_FALSE(t3.couldBe(t1));
6121 EXPECT_FALSE(t3.couldBe(t2));
6122 EXPECT_TRUE(t4.couldBe(t2));
6123 EXPECT_FALSE(t5.couldBe(t2));
6125 EXPECT_EQ(union_of(t1, t1), t1);
6126 EXPECT_EQ(union_of(t2, t2), t2);
6127 EXPECT_EQ(union_of(t1, t2), t2);
6128 EXPECT_EQ(union_of(t2, t1), t2);
6129 EXPECT_EQ(union_of(t1, t3), TSStr);
6130 EXPECT_EQ(union_of(t3, t1), TSStr);
6131 EXPECT_EQ(union_of(t2, t3), TStr);
6132 EXPECT_EQ(union_of(t3, t2), TStr);
6133 EXPECT_EQ(union_of(t2, t4), t2);
6134 EXPECT_EQ(union_of(t4, t2), t2);
6135 EXPECT_EQ(union_of(t2, t5), TStr);
6136 EXPECT_EQ(union_of(t5, t2), TStr);
6139 TEST(Type, DictMapOptValues) {
6140 auto const test_map_a = MapElems{map_elem(s_A, TInt), map_elem(s_B, TDbl)};
6141 auto const test_map_b = MapElems{map_elem(s_A, TInt)};
6142 auto const test_map_c = MapElems{map_elem(s_A, TInt), map_elem(s_test, TInt)};
6143 auto const test_map_d = MapElems{map_elem(s_test, TInt), map_elem(s_A, TInt)};
6144 auto const test_map_e = MapElems{map_elem(s_A, TInt), map_elem(s_B, TObj)};
6145 auto const test_map_f = MapElems{map_elem(10, TInt), map_elem(11, TDbl)};
6146 auto const test_map_g = MapElems{map_elem(s_A, TArrKey)};
6147 auto const test_map_h = MapElems{map_elem(s_A, TInt), map_elem(s_B, TStr)};
6148 auto const test_map_i = MapElems{map_elem(s_A, TInt), map_elem(s_B, TDbl), map_elem(s_test, TStr)};
6149 auto const test_map_j = MapElems{map_elem(s_A, TInt), map_elem(s_B, TDbl), map_elem(s_test, TObj)};
6151 EXPECT_EQ(dict_map(test_map_a, TInt, TSStr), dict_map(test_map_a, TInt, TSStr));
6152 EXPECT_NE(dict_map(test_map_a, TInt, TSStr), dict_map(test_map_a, TInt, TStr));
6154 EXPECT_FALSE(
6155 dict_map(test_map_c, TSStr, TInt).subtypeOf(dict_map(test_map_d, TSStr, TInt))
6157 EXPECT_FALSE(
6158 dict_map(test_map_a, TSStr, TInt).subtypeOf(dict_map(test_map_e, TSStr, TInt))
6160 EXPECT_FALSE(
6161 dict_map(test_map_b, TSStr, TInt).subtypeOf(dict_map(test_map_a, TSStr, TInt))
6163 EXPECT_FALSE(
6164 dict_map(test_map_a, TSStr, TInt).subtypeOf(dict_map(test_map_b, TSStr, TInt))
6166 EXPECT_TRUE(
6167 sdict_map(test_map_a, TSStr, TInt).subtypeOf(sdict_map(test_map_b, TSStr, TNum))
6169 EXPECT_FALSE(
6170 dict_map(test_map_a, TSStr, TInt).subtypeOf(dict_map(test_map_b, TInt, TNum))
6172 EXPECT_TRUE(
6173 dict_map(test_map_a, TSStr, TInt).subtypeOf(dict_map(test_map_a, TStr, TInt))
6175 EXPECT_FALSE(
6176 dict_map(test_map_a, TStr, TInt).subtypeOf(dict_map(test_map_a, TSStr, TInt))
6178 EXPECT_FALSE(
6179 dict_map(test_map_a, TSStr, TNum).subtypeOf(dict_map(test_map_a, TSStr, TInt))
6181 EXPECT_TRUE(
6182 dict_map(test_map_a, TSStr, TInt).subtypeOf(dict_n(TStr, TNum))
6184 EXPECT_FALSE(
6185 dict_map(test_map_a, TSStr, TInt).subtypeOf(dict_n(TStr, TInt))
6187 EXPECT_FALSE(
6188 dict_map(test_map_f, TSStr, TInt).subtypeOf(dict_n(TInt, TNum))
6190 EXPECT_FALSE(dict_map(test_map_a).subtypeOf(dict_n(TInt, TNum)));
6191 EXPECT_FALSE(
6192 dict_n(TSStr, TInt).subtypeOf(dict_map(test_map_a, TSStr, TInt))
6195 EXPECT_TRUE(
6196 dict_map(test_map_a, TSStr, TInt).couldBe(dict_map(test_map_a, TSStr, TInt))
6198 EXPECT_TRUE(
6199 dict_map(test_map_a, TSStr, TInt).couldBe(dict_map(test_map_a, TSStr, TNum))
6201 EXPECT_TRUE(
6202 dict_map(test_map_a, TSStr, TNum).couldBe(dict_map(test_map_a, TSStr, TInt))
6204 EXPECT_TRUE(
6205 dict_map(test_map_a, TArrKey, TInt).couldBe(dict_map(test_map_a, TSStr, TInt))
6207 EXPECT_TRUE(
6208 dict_map(test_map_a, TSStr, TInt).couldBe(dict_map(test_map_a, TArrKey, TInt))
6210 EXPECT_TRUE(
6211 dict_map(test_map_a, TSStr, TInt).couldBe(dict_map(test_map_a, TInt, TInt))
6213 EXPECT_TRUE(
6214 dict_map(test_map_a, TInt, TInt).couldBe(dict_map(test_map_a, TSStr, TInt))
6216 EXPECT_TRUE(
6217 dict_map(test_map_a, TSStr, TDbl).couldBe(dict_map(test_map_a, TSStr, TObj))
6219 EXPECT_FALSE(
6220 dict_map(test_map_a, TSStr, TInt).couldBe(dict_map(test_map_c, TSStr, TInt))
6222 EXPECT_FALSE(
6223 dict_map(test_map_c, TSStr, TInt).couldBe(dict_map(test_map_a, TSStr, TInt))
6225 EXPECT_FALSE(
6226 dict_map(test_map_a, TSStr, TInt).couldBe(dict_map(test_map_e, TSStr, TInt))
6228 EXPECT_FALSE(
6229 dict_map(test_map_e, TSStr, TInt).couldBe(dict_map(test_map_a, TSStr, TInt))
6231 EXPECT_TRUE(
6232 dict_map(test_map_a).couldBe(dict_map(test_map_b, TSStr, TDbl))
6234 EXPECT_TRUE(
6235 dict_map(test_map_b, TSStr, TDbl).couldBe(dict_map(test_map_a))
6237 EXPECT_FALSE(
6238 dict_map(test_map_a).couldBe(dict_map(test_map_b, TSStr, TObj))
6240 EXPECT_FALSE(
6241 dict_map(test_map_b, TSStr, TObj).couldBe(dict_map(test_map_a))
6244 EXPECT_EQ(
6245 union_of(sdict_map(test_map_a), sdict_map(test_map_b)),
6246 sdict_map(test_map_b, sval(s_B), TDbl)
6248 EXPECT_EQ(
6249 union_of(sdict_map(test_map_a), sdict_map(test_map_c)),
6250 sdict_map(test_map_b, TSStr, TNum)
6252 EXPECT_EQ(
6253 union_of(dict_map(test_map_a, TInt, TStr), dict_map(test_map_a, TStr, TInt)),
6254 dict_map(test_map_a, TArrKey, TArrKey)
6256 EXPECT_EQ(
6257 union_of(dict_map(test_map_c), dict_map(test_map_d)),
6258 dict_n(TSStr, TInt)
6260 EXPECT_EQ(
6261 union_of(dict_map(test_map_c, TInt, TInt), dict_map(test_map_d, TInt, TInt)),
6262 dict_n(TUncArrKey, TInt)
6264 EXPECT_EQ(
6265 union_of(
6266 dict_map(test_map_c, TSStr, TDbl),
6267 dict_map(test_map_d, TSStr, TDbl)
6269 dict_n(TSStr, TNum)
6271 EXPECT_EQ(
6272 union_of(dict_map(test_map_c, TSStr, TDbl), dict_packed({TInt})),
6273 dict_n(union_of(ival(0),TSStr), TNum)
6275 EXPECT_EQ(
6276 union_of(sdict_map(test_map_c, TSStr, TDbl), sdict_packedn(TInt)),
6277 sdict_n(TUncArrKey, TNum)
6279 EXPECT_EQ(
6280 union_of(dict_map(test_map_c, TInt, TDbl), dict_n(TSStr, TInt)),
6281 dict_n(TUncArrKey, TNum)
6284 EXPECT_EQ(
6285 intersection_of(
6286 dict_map(test_map_a, TSStr, TInt),
6287 dict_map(test_map_a, TSStr, TInt)
6289 dict_map(test_map_a, TSStr, TInt)
6291 EXPECT_EQ(
6292 intersection_of(
6293 dict_map(test_map_a, TSStr, TArrKey),
6294 dict_map(test_map_a, TSStr, TInt)
6296 dict_map(test_map_a, TSStr, TInt)
6298 EXPECT_EQ(
6299 intersection_of(
6300 dict_map(test_map_a, TSStr, TInt),
6301 dict_map(test_map_a, TArrKey, TInt)
6303 dict_map(test_map_a, TSStr, TInt)
6305 EXPECT_EQ(
6306 intersection_of(
6307 dict_map(test_map_a, TSStr, TInt),
6308 dict_map(test_map_a, TInt, TInt)
6310 dict_map(test_map_a)
6312 EXPECT_EQ(
6313 intersection_of(
6314 dict_map(test_map_a, TInt, TStr),
6315 dict_map(test_map_a, TInt, TInt)
6317 dict_map(test_map_a)
6319 EXPECT_EQ(
6320 intersection_of(
6321 dict_map(test_map_a, TInt, TInt),
6322 dict_map(test_map_e, TInt, TInt)
6324 TBottom
6326 EXPECT_EQ(
6327 intersection_of(dict_map(test_map_a), dict_map(test_map_b, TSStr, TNum)),
6328 dict_map(test_map_a)
6330 EXPECT_EQ(
6331 intersection_of(dict_map(test_map_b, TSStr, TNum), dict_map(test_map_a)),
6332 dict_map(test_map_a)
6334 EXPECT_EQ(
6335 intersection_of(dict_map(test_map_a), dict_map(test_map_b, TSStr, TObj)),
6336 TBottom
6338 EXPECT_EQ(
6339 intersection_of(dict_map(test_map_b, TSStr, TObj), dict_map(test_map_a)),
6340 TBottom
6342 EXPECT_EQ(
6343 intersection_of(dict_map(test_map_a, TSStr, TObj), dict_n(TSStr, TObj)),
6344 TBottom
6346 EXPECT_EQ(
6347 intersection_of(dict_map(test_map_a, TSStr, TObj), dict_n(TSStr, TNum)),
6348 dict_map(test_map_a)
6350 EXPECT_EQ(
6351 intersection_of(
6352 dict_map(test_map_a, TSStr, TInitCell),
6353 dict_n(TSStr, TNum)
6355 dict_map(test_map_a, TSStr, TNum)
6358 EXPECT_EQ(
6359 array_like_set(dict_map(test_map_b), TSStr, TStr).first,
6360 dict_map(test_map_g, TSStr, TStr)
6362 EXPECT_EQ(
6363 array_like_set(dict_map(test_map_a), sval(s_B), TStr).first,
6364 dict_map(test_map_h)
6366 EXPECT_EQ(
6367 array_like_set(dict_map(test_map_a), sval(s_test), TStr).first,
6368 dict_map(test_map_i)
6370 EXPECT_EQ(
6371 array_like_set(dict_map(test_map_a, TSStr, TInt), sval(s_test), TStr).first,
6372 dict_map(test_map_a, TSStr, TArrKey)
6374 EXPECT_EQ(
6375 array_like_set(
6376 dict_map(test_map_a, sval(s_test), TInt),
6377 sval(s_test),
6378 TObj
6379 ).first,
6380 dict_map(test_map_j)
6384 TEST(Type, ContextDependent) {
6385 // This only covers basic cases involving objects. More testing should
6386 // be added for non object types, and nested types.
6387 auto const program = make_test_program();
6388 auto const unit = program->units.back().get();
6389 auto const func = [&]() -> php::Func* {
6390 for (auto& f : unit->funcs) {
6391 if (f->name->isame(s_test.get())) return f.get();
6393 return nullptr;
6394 }();
6395 EXPECT_TRUE(func != nullptr);
6397 auto const ctx = Context { unit, func };
6398 Index idx{program.get()};
6400 // load classes in hierarchy Base -> B -> BB
6401 auto const clsBase = idx.resolve_class(ctx, s_Base.get());
6402 if (!clsBase) ADD_FAILURE();
6403 auto const clsB = idx.resolve_class(ctx, s_B.get());
6404 if (!clsB) ADD_FAILURE();
6405 auto const clsBB = idx.resolve_class(ctx, s_BB.get());
6406 if (!clsBB) ADD_FAILURE();
6407 // Unrelated class.
6408 auto const clsUn = idx.resolve_class(ctx, s_TestClass.get());
6409 if (!clsUn) ADD_FAILURE();
6411 auto const objExactBaseTy = objExact(*clsBase);
6412 auto const thisObjExactBaseTy = setctx(objExact(*clsBase));
6413 auto const subObjBaseTy = subObj(*clsBase);
6414 auto const thisSubObjBaseTy = setctx(subObj(*clsBase));
6416 auto const objExactBTy = objExact(*clsB);
6417 auto const thisObjExactBTy = setctx(objExact(*clsB));
6418 auto const subObjBTy = subObj(*clsB);
6419 auto const thisSubObjBTy = setctx(subObj(*clsB));
6420 auto const clsExactBTy = clsExact(*clsB);
6421 auto const thisClsExactBTy = setctx(clsExact(*clsB));
6422 auto const subClsBTy = subCls(*clsB);
6423 auto const thisSubClsBTy = setctx(subCls(*clsB));
6425 auto const objExactBBTy = objExact(*clsBB);
6426 auto const thisObjExactBBTy = setctx(objExact(*clsBB));
6427 auto const subObjBBTy = subObj(*clsBB);
6428 auto const thisSubObjBBTy = setctx(subObj(*clsBB));
6429 auto const clsExactBBTy = clsExact(*clsBB);
6430 auto const thisClsExactBBTy = setctx(clsExact(*clsBB));
6431 auto const subClsBBTy = subCls(*clsBB);
6432 auto const thisSubClsBBTy = setctx(subCls(*clsBB));
6434 auto const objExactUnTy = objExact(*clsUn);
6435 auto const thisObjExactUnTy = setctx(objExact(*clsUn));
6436 auto const subObjUnTy = subObj(*clsUn);
6437 auto const thisSubObjUnTy = setctx(subObj(*clsUn));
6439 #define REFINE_EQ(A, B) \
6440 EXPECT_TRUE((A).equivalentlyRefined((B)))
6441 #define REFINE_NEQ(A, B) \
6442 EXPECT_FALSE((A).equivalentlyRefined((B)))
6444 // check that improving any non context dependent type does not change the
6445 // type whether or not the context is related.
6446 REFINE_EQ(return_with_context(objExactBaseTy, objExactBTy),
6447 objExactBaseTy);
6448 REFINE_EQ(return_with_context(subObjBaseTy, objExactBTy),
6449 subObjBaseTy);
6450 REFINE_EQ(return_with_context(objExactBTy, objExactBTy),
6451 objExactBTy);
6452 REFINE_EQ(return_with_context(subObjBTy, objExactBTy),
6453 subObjBTy);
6454 REFINE_EQ(return_with_context(objExactBBTy, objExactBTy),
6455 objExactBBTy);
6456 REFINE_EQ(return_with_context(subObjBBTy, objExactBTy),
6457 subObjBBTy);
6458 REFINE_EQ(return_with_context(objExactUnTy, objExactBTy),
6459 objExactUnTy);
6460 REFINE_EQ(return_with_context(subObjUnTy, objExactBTy),
6461 subObjUnTy);
6462 REFINE_EQ(return_with_context(objExactBaseTy, clsExactBTy),
6463 objExactBaseTy);
6464 REFINE_EQ(return_with_context(subObjBaseTy, clsExactBTy),
6465 subObjBaseTy);
6466 REFINE_EQ(return_with_context(objExactBTy, clsExactBTy),
6467 objExactBTy);
6468 REFINE_EQ(return_with_context(subObjBTy, clsExactBTy),
6469 subObjBTy);
6470 REFINE_EQ(return_with_context(objExactBBTy, clsExactBTy),
6471 objExactBBTy);
6472 REFINE_EQ(return_with_context(subObjBBTy, clsExactBTy),
6473 subObjBBTy);
6474 REFINE_EQ(return_with_context(objExactUnTy, clsExactBTy),
6475 objExactUnTy);
6476 REFINE_EQ(return_with_context(subObjUnTy, clsExactBTy),
6477 subObjUnTy);
6479 // With sub.
6480 REFINE_EQ(return_with_context(objExactBaseTy, subObjBTy),
6481 objExactBaseTy);
6482 REFINE_EQ(return_with_context(subObjBaseTy, subObjBTy),
6483 subObjBaseTy);
6484 REFINE_EQ(return_with_context(objExactBTy, subObjBTy),
6485 objExactBTy);
6486 REFINE_EQ(return_with_context(subObjBTy, subObjBTy),
6487 subObjBTy);
6488 REFINE_EQ(return_with_context(objExactBBTy, subObjBTy),
6489 objExactBBTy);
6490 REFINE_EQ(return_with_context(subObjBBTy, subObjBTy),
6491 subObjBBTy);
6492 REFINE_EQ(return_with_context(objExactUnTy, subObjBTy),
6493 objExactUnTy);
6494 REFINE_EQ(return_with_context(subObjUnTy, subObjBTy),
6495 subObjUnTy);
6496 REFINE_EQ(return_with_context(objExactBaseTy, subClsBTy),
6497 objExactBaseTy);
6498 REFINE_EQ(return_with_context(subObjBaseTy, subClsBTy),
6499 subObjBaseTy);
6500 REFINE_EQ(return_with_context(objExactBTy, subClsBTy),
6501 objExactBTy);
6502 REFINE_EQ(return_with_context(subObjBTy, subClsBTy),
6503 subObjBTy);
6504 REFINE_EQ(return_with_context(objExactBBTy, subClsBTy),
6505 objExactBBTy);
6506 REFINE_EQ(return_with_context(subObjBBTy, subClsBTy),
6507 subObjBBTy);
6508 REFINE_EQ(return_with_context(objExactUnTy, subClsBTy),
6509 objExactUnTy);
6510 REFINE_EQ(return_with_context(subObjUnTy, subClsBTy),
6511 subObjUnTy);
6513 // Improvements (exact)
6514 REFINE_EQ(return_with_context(thisObjExactBaseTy, objExactBTy),
6515 TBottom);
6516 REFINE_EQ(return_with_context(thisSubObjBaseTy, objExactBTy),
6517 objExactBTy);
6518 REFINE_EQ(return_with_context(thisObjExactBTy, objExactBTy),
6519 objExactBTy);
6520 REFINE_EQ(return_with_context(thisSubObjBTy, objExactBTy),
6521 objExactBTy);
6522 REFINE_EQ(return_with_context(thisObjExactBBTy, objExactBTy),
6523 TBottom);
6524 REFINE_EQ(return_with_context(thisSubObjBBTy, objExactBTy),
6525 TBottom);
6526 REFINE_EQ(return_with_context(thisObjExactUnTy, objExactBTy),
6527 TBottom);
6528 REFINE_EQ(return_with_context(thisSubObjUnTy, objExactBTy),
6529 TBottom);
6530 REFINE_EQ(return_with_context(thisObjExactBaseTy, clsExactBTy),
6531 TBottom);
6532 REFINE_EQ(return_with_context(thisSubObjBaseTy, clsExactBTy),
6533 objExactBTy);
6534 REFINE_EQ(return_with_context(thisObjExactBTy, clsExactBTy),
6535 objExactBTy);
6536 REFINE_EQ(return_with_context(thisSubObjBTy, clsExactBTy),
6537 objExactBTy);
6538 REFINE_EQ(return_with_context(thisObjExactBBTy, clsExactBTy),
6539 TBottom);
6540 REFINE_EQ(return_with_context(thisSubObjBBTy, clsExactBTy),
6541 TBottom);
6542 REFINE_EQ(return_with_context(thisObjExactUnTy, clsExactBTy),
6543 TBottom);
6544 REFINE_EQ(return_with_context(thisSubObjUnTy, clsExactBTy),
6545 TBottom);
6546 REFINE_EQ(return_with_context(thisObjExactBaseTy, thisObjExactBTy),
6547 TBottom);
6548 REFINE_EQ(return_with_context(thisSubObjBaseTy, thisObjExactBTy),
6549 thisObjExactBTy);
6550 REFINE_EQ(return_with_context(thisObjExactBTy, thisObjExactBTy),
6551 thisObjExactBTy);
6552 REFINE_EQ(return_with_context(thisSubObjBTy, thisObjExactBTy),
6553 thisObjExactBTy);
6554 REFINE_EQ(return_with_context(thisObjExactBBTy, thisObjExactBTy),
6555 TBottom);
6556 REFINE_EQ(return_with_context(thisSubObjBBTy, thisObjExactBTy),
6557 TBottom);
6558 REFINE_EQ(return_with_context(thisObjExactUnTy, thisObjExactBTy),
6559 TBottom);
6560 REFINE_EQ(return_with_context(thisSubObjUnTy, thisObjExactBTy),
6561 TBottom);
6562 REFINE_EQ(return_with_context(thisObjExactBaseTy, thisClsExactBTy),
6563 TBottom);
6564 REFINE_EQ(return_with_context(thisSubObjBaseTy, thisClsExactBTy),
6565 thisObjExactBTy);
6566 REFINE_EQ(return_with_context(thisObjExactBTy, thisClsExactBTy),
6567 thisObjExactBTy);
6568 REFINE_EQ(return_with_context(thisSubObjBTy, thisClsExactBTy),
6569 thisObjExactBTy);
6570 REFINE_EQ(return_with_context(thisObjExactBBTy, thisClsExactBTy),
6571 TBottom);
6572 REFINE_EQ(return_with_context(thisSubObjBBTy, thisClsExactBTy),
6573 TBottom);
6574 REFINE_EQ(return_with_context(thisObjExactUnTy, thisClsExactBTy),
6575 TBottom);
6576 REFINE_EQ(return_with_context(thisSubObjUnTy, thisClsExactBTy),
6577 TBottom);
6579 // Improvements (sub)
6580 REFINE_EQ(return_with_context(thisObjExactBaseTy, subObjBTy),
6581 TBottom);
6582 REFINE_EQ(return_with_context(thisSubObjBaseTy, subObjBTy),
6583 subObjBTy);
6584 REFINE_EQ(return_with_context(thisObjExactBTy, subObjBTy),
6585 objExactBTy);
6586 REFINE_EQ(return_with_context(thisSubObjBTy, subObjBTy),
6587 subObjBTy);
6588 REFINE_EQ(return_with_context(thisObjExactBBTy, subObjBTy),
6589 objExactBBTy);
6590 REFINE_EQ(return_with_context(thisSubObjBBTy, subObjBTy),
6591 subObjBBTy);
6592 REFINE_EQ(return_with_context(thisObjExactUnTy, subObjBTy),
6593 TBottom);
6594 REFINE_EQ(return_with_context(thisSubObjUnTy, subObjBTy),
6595 TBottom);
6596 REFINE_EQ(return_with_context(thisObjExactBaseTy, subClsBTy),
6597 TBottom);
6598 REFINE_EQ(return_with_context(thisSubObjBaseTy, subClsBTy),
6599 subObjBTy);
6600 REFINE_EQ(return_with_context(thisObjExactBTy, subClsBTy),
6601 objExactBTy);
6602 REFINE_EQ(return_with_context(thisSubObjBTy, subClsBTy),
6603 subObjBTy);
6604 REFINE_EQ(return_with_context(thisObjExactBBTy, subClsBTy),
6605 objExactBBTy);
6606 REFINE_EQ(return_with_context(thisSubObjBBTy, subClsBTy),
6607 subObjBBTy);
6608 REFINE_EQ(return_with_context(thisObjExactUnTy, subClsBTy),
6609 TBottom);
6610 REFINE_EQ(return_with_context(thisSubObjUnTy, subClsBTy),
6611 TBottom);
6612 REFINE_EQ(return_with_context(thisObjExactBaseTy, thisSubObjBTy),
6613 TBottom);
6614 REFINE_EQ(return_with_context(thisSubObjBaseTy, thisSubObjBTy),
6615 thisSubObjBTy);
6616 REFINE_EQ(return_with_context(thisObjExactBTy, thisSubObjBTy),
6617 thisObjExactBTy);
6618 REFINE_EQ(return_with_context(thisSubObjBTy, thisSubObjBTy),
6619 thisSubObjBTy);
6620 REFINE_EQ(return_with_context(thisObjExactBBTy, thisSubObjBTy),
6621 thisObjExactBBTy);
6622 REFINE_EQ(return_with_context(thisSubObjBBTy, thisSubObjBTy),
6623 thisSubObjBBTy);
6624 REFINE_EQ(return_with_context(thisObjExactUnTy, thisSubObjBTy),
6625 TBottom);
6626 REFINE_EQ(return_with_context(thisSubObjUnTy, thisSubObjBTy),
6627 TBottom);
6628 REFINE_EQ(return_with_context(thisObjExactBaseTy, thisSubClsBTy),
6629 TBottom);
6630 REFINE_EQ(return_with_context(thisSubObjBaseTy, thisSubClsBTy),
6631 thisSubObjBTy);
6632 REFINE_EQ(return_with_context(thisObjExactBTy, thisSubClsBTy),
6633 thisObjExactBTy);
6634 REFINE_EQ(return_with_context(thisSubObjBTy, thisSubClsBTy),
6635 thisSubObjBTy);
6636 REFINE_EQ(return_with_context(thisObjExactBBTy, thisSubClsBTy),
6637 thisObjExactBBTy);
6638 REFINE_EQ(return_with_context(thisSubObjBBTy, thisSubClsBTy),
6639 thisSubObjBBTy);
6640 REFINE_EQ(return_with_context(thisObjExactUnTy, thisSubClsBTy),
6641 TBottom);
6642 REFINE_EQ(return_with_context(thisSubObjUnTy, thisSubClsBTy),
6643 TBottom);
6645 // Optional type preservation.
6646 REFINE_EQ(return_with_context(opt(subObjBaseTy), objExactBTy),
6647 opt(subObjBaseTy));
6648 REFINE_EQ(return_with_context(opt(subObjBaseTy), clsExactBTy),
6649 opt(subObjBaseTy));
6650 REFINE_EQ(return_with_context(opt(subObjBaseTy), subObjBTy),
6651 opt(subObjBaseTy));
6652 REFINE_EQ(return_with_context(opt(subObjBaseTy), subClsBTy),
6653 opt(subObjBaseTy));
6654 REFINE_EQ(return_with_context(opt(thisSubObjBaseTy), objExactBTy),
6655 opt(objExactBTy));
6656 REFINE_EQ(return_with_context(opt(thisSubObjBaseTy), clsExactBTy),
6657 opt(objExactBTy));
6658 REFINE_EQ(return_with_context(opt(thisSubObjBaseTy), thisObjExactBTy),
6659 opt(thisObjExactBTy));
6660 REFINE_EQ(return_with_context(opt(thisSubObjBaseTy), thisClsExactBTy),
6661 opt(thisObjExactBTy));
6664 // Refinedness operators.
6665 REFINE_EQ(objExactBTy, objExactBTy);
6666 REFINE_EQ(subObjBTy, subObjBTy);
6667 REFINE_EQ(clsExactBTy, clsExactBTy);
6668 REFINE_EQ(subClsBTy, subClsBTy);
6669 REFINE_EQ(thisObjExactBTy, thisObjExactBTy);
6670 REFINE_EQ(thisSubObjBTy, thisSubObjBTy);
6671 REFINE_EQ(thisClsExactBTy, thisClsExactBTy);
6672 REFINE_EQ(thisSubClsBTy, thisSubClsBTy);
6674 REFINE_NEQ(objExactBTy, thisObjExactBTy);
6675 REFINE_NEQ(subObjBTy, thisSubObjBTy);
6676 REFINE_NEQ(clsExactBTy, thisClsExactBTy);
6677 REFINE_NEQ(subClsBTy, thisSubClsBTy);
6678 REFINE_NEQ(thisObjExactBTy, objExactBTy);
6679 REFINE_NEQ(thisSubObjBTy, subObjBTy);
6680 REFINE_NEQ(thisClsExactBTy, clsExactBTy);
6681 REFINE_NEQ(thisSubClsBTy, subClsBTy);
6683 EXPECT_FALSE(objExactBTy.moreRefined(thisObjExactBTy));
6684 EXPECT_FALSE(subObjBTy.moreRefined(thisSubObjBTy));
6685 EXPECT_FALSE(clsExactBTy.moreRefined(thisClsExactBTy));
6686 EXPECT_FALSE(subClsBTy.moreRefined(thisSubClsBTy));
6688 EXPECT_TRUE(thisObjExactBTy.moreRefined(objExactBTy));
6689 EXPECT_TRUE(thisSubObjBTy.moreRefined(subObjBTy));
6690 EXPECT_TRUE(thisClsExactBTy.moreRefined(clsExactBTy));
6691 EXPECT_TRUE(thisSubClsBTy.moreRefined(subClsBTy));
6693 EXPECT_TRUE(thisObjExactBTy.moreRefined(thisObjExactBTy));
6694 EXPECT_TRUE(thisSubObjBTy.moreRefined(thisSubObjBTy));
6695 EXPECT_TRUE(thisClsExactBTy.moreRefined(thisClsExactBTy));
6696 EXPECT_TRUE(thisSubClsBTy.moreRefined(thisSubClsBTy));
6698 EXPECT_FALSE(thisObjExactBTy.strictlyMoreRefined(thisObjExactBTy));
6699 EXPECT_FALSE(thisSubObjBTy.strictlyMoreRefined(thisSubObjBTy));
6700 EXPECT_FALSE(thisClsExactBTy.strictlyMoreRefined(thisClsExactBTy));
6701 EXPECT_FALSE(thisSubClsBTy.strictlyMoreRefined(thisSubClsBTy));
6703 EXPECT_FALSE(thisObjExactBBTy.strictlyMoreRefined(thisObjExactBTy));
6704 EXPECT_TRUE(thisSubObjBBTy.strictlyMoreRefined(thisSubObjBTy));
6705 EXPECT_FALSE(thisClsExactBBTy.strictlyMoreRefined(thisClsExactBTy));
6706 EXPECT_TRUE(thisSubClsBBTy.strictlyMoreRefined(thisSubClsBTy));
6708 EXPECT_FALSE(thisObjExactBTy.strictlyMoreRefined(thisObjExactBBTy));
6709 EXPECT_FALSE(thisSubObjBTy.strictlyMoreRefined(thisSubObjBBTy));
6710 EXPECT_FALSE(thisClsExactBTy.strictlyMoreRefined(thisClsExactBBTy));
6711 EXPECT_FALSE(thisSubClsBTy.strictlyMoreRefined(thisSubClsBBTy));
6713 EXPECT_FALSE(objExactBBTy.strictlyMoreRefined(thisObjExactBTy));
6714 EXPECT_FALSE(subObjBBTy.strictlyMoreRefined(thisSubObjBTy));
6715 EXPECT_FALSE(clsExactBBTy.strictlyMoreRefined(thisClsExactBTy));
6716 EXPECT_FALSE(subClsBBTy.strictlyMoreRefined(thisSubClsBTy));
6718 // Normal equality should still hold.
6719 EXPECT_EQ(objExactBTy, thisObjExactBTy);
6720 EXPECT_EQ(subObjBTy, thisSubObjBTy);
6721 EXPECT_EQ(clsExactBTy, thisClsExactBTy);
6722 EXPECT_EQ(subClsBTy, thisSubClsBTy);
6723 EXPECT_EQ(thisObjExactBTy, objExactBTy);
6724 EXPECT_EQ(thisSubObjBTy, subObjBTy);
6725 EXPECT_EQ(thisClsExactBTy, clsExactBTy);
6726 EXPECT_EQ(thisSubClsBTy, subClsBTy);
6728 auto const& types = allCases(idx);
6729 auto const test = [&] (const Type& context) {
6730 for (auto const& t: types) {
6731 if (!t.subtypeOf(BInitCell)) continue;
6732 auto const [obj, objRest] = split_obj(t);
6733 auto const [cls, clsRest] = split_cls(objRest);
6734 REFINE_EQ(
6735 return_with_context(t, context),
6736 union_of(
6737 return_with_context(obj, context),
6738 return_with_context(cls, context),
6739 clsRest
6744 test(objExactBTy);
6745 test(clsExactBTy);
6746 test(subObjBTy);
6747 test(subClsBTy);
6748 test(thisObjExactBTy);
6749 test(thisClsExactBTy);
6750 test(thisSubObjBTy);
6751 test(thisSubClsBTy);
6753 #undef REFINE_NEQ
6754 #undef REFINE_EQ
6757 TEST(Type, ArrLike) {
6758 const std::initializer_list<std::pair<Type, Type>> subtype_true{
6759 // Expect all static arrays to be subtypes
6760 { TSKeyset, TArrLike },
6761 { TSDict, TArrLike },
6762 { TSVec, TArrLike },
6763 // Expect other arrays to be subtypes
6764 { TKeyset, TArrLike },
6765 { TDict, TArrLike },
6766 { TVec, TArrLike },
6769 const std::initializer_list<std::pair<Type, Type>> subtype_false{
6770 // ClsMeth is not an array
6771 { TClsMeth, TArrLike },
6772 // Ints are not arrays
6773 { TInt, TArrLike },
6774 // ArrLike doesn't contain null
6775 { TOptVec, TArrLike },
6778 const std::initializer_list<std::pair<Type, Type>> couldbe_true{
6779 { TArrLike, TOptKeysetE },
6782 const std::initializer_list<std::pair<Type, Type>> couldbe_false{
6783 { TArrLike, TPrim },
6784 { TArrLike, TNull },
6787 for (auto kv : subtype_true) {
6788 EXPECT_TRUE(kv.first.subtypeOf(kv.second))
6789 << show(kv.first) << " subtypeOf " << show(kv.second);
6792 for (auto kv : subtype_false) {
6793 EXPECT_FALSE(kv.first.subtypeOf(kv.second))
6794 << show(kv.first) << " !subtypeOf " << show(kv.second);
6797 for (auto kv : couldbe_true) {
6798 EXPECT_TRUE(kv.first.couldBe(kv.second))
6799 << show(kv.first) << " couldbe " << show(kv.second);
6800 EXPECT_TRUE(kv.second.couldBe(kv.first))
6801 << show(kv.first) << " couldbe " << show(kv.second);
6804 for (auto kv : couldbe_false) {
6805 EXPECT_FALSE(kv.first.couldBe(kv.second))
6806 << show(kv.first) << " !couldbe " << show(kv.second);
6807 EXPECT_FALSE(kv.second.couldBe(kv.first))
6808 << show(kv.first) << " !couldbe " << show(kv.second);
6812 TEST(Type, LoosenLikeness) {
6813 auto const program = make_test_program();
6814 Index index{ program.get() };
6816 auto const& all = allCases(index);
6817 for (auto const& t : all) {
6818 if (!t.couldBe(BCls | BLazyCls | BClsMeth)) {
6819 EXPECT_EQ(loosen_likeness(t), t);
6820 } else {
6821 auto u = BBottom;
6822 if (t.couldBe(BCls | BLazyCls)) u |= BSStr;
6823 EXPECT_EQ(loosen_likeness(t), union_of(t, Type{u}));
6827 std::vector<std::pair<Type, Type>> tests{
6828 { TClsMeth, Type{BClsMeth} },
6829 { TCls, Type{BCls|BSStr} },
6830 { TLazyCls, Type{BLazyCls|BSStr} },
6831 { lazyclsval(s_A), Type{BLazyCls|BSStr} },
6832 { TInt, TInt },
6833 { Type{BInt|BCls}, Type{BCls|BSStr|BInt} },
6834 { Type{BInt|BLazyCls}, Type{BLazyCls|BSStr|BInt} }
6836 for (auto const& p : tests) {
6837 EXPECT_EQ(loosen_likeness(p.first), p.second);
6841 TEST(Type, LoosenLikenessRecursively) {
6842 auto const program = make_test_program();
6843 Index index{ program.get() };
6845 auto const test = [&] (const Type& t) {
6846 if (!t.subtypeOf(BInitCell)) return;
6848 if (!t.is(BBottom)) {
6849 EXPECT_EQ(loosen_likeness_recursively(opt(t)),
6850 opt(loosen_likeness_recursively(t)));
6851 EXPECT_EQ(
6852 loosen_likeness_recursively(wait_handle(index, t)),
6853 wait_handle(index, loosen_likeness_recursively(t)));
6854 EXPECT_EQ(
6855 loosen_likeness_recursively(vec_n(t)),
6856 vec_n(loosen_likeness_recursively(t)));
6857 EXPECT_EQ(
6858 loosen_likeness_recursively(vec({t})),
6859 vec({loosen_likeness_recursively(t)}));
6860 EXPECT_EQ(
6861 loosen_likeness_recursively(dict_n(TArrKey, t)),
6862 dict_n(TArrKey, loosen_likeness_recursively(t)));
6863 EXPECT_EQ(
6864 loosen_likeness_recursively(dict_map({map_elem(s_A, t)}, TArrKey, t)),
6865 dict_map({map_elem(s_A, loosen_likeness_recursively(t))},
6866 TArrKey, loosen_likeness_recursively(t)));
6869 if (t.couldBe(BArrLikeN | BObj)) return;
6871 auto u = BBottom;
6872 if (t.couldBe(BCls | BLazyCls)) u |= BSStr;
6873 EXPECT_EQ(loosen_likeness_recursively(t), union_of(t, Type{u}));
6876 auto const almostAll1 = Type{BInitCell & ~BSStr};
6877 auto const almostAll2 = Type{BInitCell};
6879 auto const& all = allCases(index);
6880 for (auto const& t : all) test(t);
6881 test(almostAll1);
6882 test(almostAll2);
6884 std::vector<std::pair<Type, Type>> tests{
6885 { TClsMeth, Type{BClsMeth} },
6886 { TCls, Type{BCls|BSStr} },
6887 { TLazyCls, Type{BLazyCls|BSStr} },
6888 { TInt, TInt },
6889 { Type{BInt|BCls}, Type{BCls|BSStr|BInt} },
6890 { wait_handle(index, TInt), wait_handle(index, TInt) },
6891 { wait_handle(index, TCls), wait_handle(index, Type{BCls|BSStr}) },
6892 { wait_handle(index, TClsMeth), wait_handle(index, Type{BClsMeth}) },
6893 { vec_n(TInt), vec_n(TInt) },
6894 { vec_n(TCls), vec_n(Type{BCls|BSStr}) },
6895 { vec_n(TClsMeth), vec_n(Type{BClsMeth}) },
6896 { vec({TInt}), vec({TInt}) },
6897 { vec({TCls}), vec({Type{BCls|BSStr}}) },
6898 { vec({TClsMeth}), vec({Type{BClsMeth}}) },
6899 { dict_n(TArrKey, TInt), dict_n(TArrKey, TInt) },
6900 { dict_n(TArrKey, TCls), dict_n(TArrKey, Type{BCls|BSStr}) },
6901 { dict_n(TArrKey, TClsMeth), dict_n(TArrKey, Type{BClsMeth}) },
6902 { dict_map({map_elem(s_A, TInt)}, TArrKey, TInt),
6903 dict_map({map_elem(s_A, TInt)}, TArrKey, TInt) },
6904 { dict_map({map_elem(s_A, TCls)}, TArrKey, TCls),
6905 dict_map({map_elem(s_A, Type{BCls|BSStr})}, TArrKey, Type{BCls|BSStr}) },
6906 { dict_map({map_elem(s_A, TClsMeth)}, TArrKey, TClsMeth),
6907 dict_map({map_elem(s_A, Type{BClsMeth})}, TArrKey, Type{BClsMeth}) },
6908 { vec_n(almostAll1), TVecN },
6909 { vec_n(almostAll2), TVecN },
6910 { dict_n(TArrKey, almostAll1), TDictN },
6911 { dict_n(TArrKey, almostAll2), TDictN }
6913 for (auto const& p : tests) {
6914 EXPECT_EQ(loosen_mark_for_testing(loosen_likeness_recursively(p.first)),
6915 loosen_mark_for_testing(p.second));
6919 TEST(Type, IterTypes) {
6920 auto const elem1 = map_elem(s_A, TObj);
6921 auto const elem2 = map_elem_nonstatic(s_B, TInt);
6922 auto const sdict1 = static_dict(s_A, 100);
6923 auto const sdict2 = static_dict(s_A, 100, s_B, 200);
6925 std::vector<std::pair<Type, IterTypes>> tests{
6926 { TInt, { TBottom, TBottom, IterTypes::Count::Empty, true, true } },
6927 { TInitNull, { TBottom, TBottom, IterTypes::Count::Empty, true, true } },
6928 { Type{BObj|BArrLike}, { TInitCell, TInitCell, IterTypes::Count::Any, true, true } },
6929 { Type{BInt|BArrLike}, { TInitCell, TInitCell, IterTypes::Count::Any, true, false } },
6930 { TVecE, { TBottom, TBottom, IterTypes::Count::Empty, false, false } },
6931 { TOptVecE, { TBottom, TBottom, IterTypes::Count::Empty, true, false } },
6933 { TSVec, { TInt, TInitUnc, IterTypes::Count::Any, false, false } },
6934 { TOptSVec, { TInt, TInitUnc, IterTypes::Count::Any, true, false } },
6935 { TSVecN, { TInt, TInitUnc, IterTypes::Count::NonEmpty, false, false } },
6936 { TOptSVecN, { TInt, TInitUnc, IterTypes::Count::Any, true, false } },
6938 { TSKeyset, { TUncArrKey, TUncArrKey, IterTypes::Count::Any, false, false } },
6939 { TOptSKeyset, { TUncArrKey, TUncArrKey, IterTypes::Count::Any, true, false } },
6940 { TSKeysetN, { TUncArrKey, TUncArrKey, IterTypes::Count::NonEmpty, false, false } },
6941 { TOptSKeysetN, { TUncArrKey, TUncArrKey, IterTypes::Count::Any, true, false } },
6943 { TSArrLike, { TUncArrKey, TInitUnc, IterTypes::Count::Any, false, false } },
6944 { TOptSArrLike, { TUncArrKey, TInitUnc, IterTypes::Count::Any, true, false } },
6945 { TSArrLikeN, { TUncArrKey, TInitUnc, IterTypes::Count::NonEmpty, false, false } },
6946 { TOptSArrLikeN, { TUncArrKey, TInitUnc, IterTypes::Count::Any, true, false } },
6948 { TVec, { TInt, TInitCell, IterTypes::Count::Any, false, false } },
6949 { TOptVec, { TInt, TInitCell, IterTypes::Count::Any, true, false } },
6950 { TVecN, { TInt, TInitCell, IterTypes::Count::NonEmpty, false, false } },
6951 { TOptVecN, { TInt, TInitCell, IterTypes::Count::Any, true, false } },
6953 { TKeyset, { TArrKey, TArrKey, IterTypes::Count::Any, false, false } },
6954 { TOptKeyset, { TArrKey, TArrKey, IterTypes::Count::Any, true, false } },
6955 { TKeysetN, { TArrKey, TArrKey, IterTypes::Count::NonEmpty, false, false } },
6956 { TOptKeysetN, { TArrKey, TArrKey, IterTypes::Count::Any, true, false } },
6958 { TArrLike, { TArrKey, TInitCell, IterTypes::Count::Any, false, false } },
6959 { TOptArrLike, { TArrKey, TInitCell, IterTypes::Count::Any, true, false } },
6960 { TArrLikeN, { TArrKey, TInitCell, IterTypes::Count::NonEmpty, false, false } },
6961 { TOptArrLikeN, { TArrKey, TInitCell, IterTypes::Count::Any, true, false } },
6963 { make_specialized_arrval(BSDict, sdict1), { sval(s_A), ival(100), IterTypes::Count::ZeroOrOne, false, false } },
6964 { make_specialized_arrval(BOptSDict, sdict1), { sval(s_A), ival(100), IterTypes::Count::ZeroOrOne, true, false } },
6965 { make_specialized_arrval(BSDictN, sdict1), { sval(s_A), ival(100), IterTypes::Count::Single, false, false } },
6966 { make_specialized_arrval(BOptSDictN, sdict1), { sval(s_A), ival(100), IterTypes::Count::ZeroOrOne, true, false } },
6968 { make_specialized_arrval(BSDict, sdict2), { TSStr, TInt, IterTypes::Count::Any, false, false } },
6969 { make_specialized_arrval(BOptSDict, sdict2), { TSStr, TInt, IterTypes::Count::Any, true, false } },
6970 { make_specialized_arrval(BSDictN, sdict2), { TSStr, TInt, IterTypes::Count::NonEmpty, false, false } },
6971 { make_specialized_arrval(BOptSDictN, sdict2), { TSStr, TInt, IterTypes::Count::Any, true, false } },
6973 { make_specialized_arrpackedn(BVec, TObj), { TInt, TObj, IterTypes::Count::Any, false, false } },
6974 { make_specialized_arrpackedn(BOptVec, TObj), { TInt, TObj, IterTypes::Count::Any, true, false } },
6975 { make_specialized_arrpackedn(BVecN, TObj), { TInt, TObj, IterTypes::Count::NonEmpty, false, false } },
6976 { make_specialized_arrpackedn(BOptVecN, TObj), { TInt, TObj, IterTypes::Count::Any, true, false } },
6978 { make_specialized_arrpacked(BVec, {TObj}), { ival(0), TObj, IterTypes::Count::ZeroOrOne, false, false } },
6979 { make_specialized_arrpacked(BOptVec, {TObj}), { ival(0), TObj, IterTypes::Count::ZeroOrOne, true, false } },
6980 { make_specialized_arrpacked(BVecN, {TObj}), { ival(0), TObj, IterTypes::Count::Single, false, false } },
6981 { make_specialized_arrpacked(BOptVecN, {TObj}), { ival(0), TObj, IterTypes::Count::ZeroOrOne, true, false } },
6983 { make_specialized_arrpacked(BVec, {TObj,TStr}), { TInt, Type{BObj|BStr}, IterTypes::Count::Any, false, false } },
6984 { make_specialized_arrpacked(BOptVec, {TObj,TStr}), { TInt, Type{BObj|BStr}, IterTypes::Count::Any, true, false } },
6985 { make_specialized_arrpacked(BVecN, {TObj,TStr}), { TInt, Type{BObj|BStr}, IterTypes::Count::NonEmpty, false, false } },
6986 { make_specialized_arrpacked(BOptVecN, {TObj,TStr}), { TInt, Type{BObj|BStr}, IterTypes::Count::Any, true, false } },
6988 { make_specialized_arrmapn(BDict, TStr, TObj), { TStr, TObj, IterTypes::Count::Any, false, false } },
6989 { make_specialized_arrmapn(BOptDict, TStr, TObj), { TStr, TObj, IterTypes::Count::Any, true, false } },
6990 { make_specialized_arrmapn(BDictN, TStr, TObj), { TStr, TObj, IterTypes::Count::NonEmpty, false, false } },
6991 { make_specialized_arrmapn(BOptDictN, TStr, TObj), { TStr, TObj, IterTypes::Count::Any, true, false } },
6993 { make_specialized_arrmap(BDict, {elem1}), { sval(s_A), TObj, IterTypes::Count::ZeroOrOne, false, false } },
6994 { make_specialized_arrmap(BOptDict, {elem1}), { sval(s_A), TObj, IterTypes::Count::ZeroOrOne, true, false } },
6995 { make_specialized_arrmap(BDictN, {elem1}), { sval(s_A), TObj, IterTypes::Count::Single, false, false } },
6996 { make_specialized_arrmap(BOptDictN, {elem1}), { sval(s_A), TObj, IterTypes::Count::ZeroOrOne, true, false } },
6998 { make_specialized_arrmap(BDict, {elem2}), { sval_nonstatic(s_B), TInt, IterTypes::Count::ZeroOrOne, false, false } },
6999 { make_specialized_arrmap(BOptDict, {elem2}), { sval_nonstatic(s_B), TInt, IterTypes::Count::ZeroOrOne, true, false } },
7000 { make_specialized_arrmap(BDictN, {elem2}), { sval_nonstatic(s_B), TInt, IterTypes::Count::Single, false, false } },
7001 { make_specialized_arrmap(BOptDictN, {elem2}), { sval_nonstatic(s_B), TInt, IterTypes::Count::ZeroOrOne, true, false } },
7003 { make_specialized_arrmap(BDict, {elem1,elem2}), { TStr, Type{BObj|BInt}, IterTypes::Count::Any, false, false } },
7004 { make_specialized_arrmap(BOptDict, {elem1,elem2}), { TStr, Type{BObj|BInt}, IterTypes::Count::Any, true, false } },
7005 { make_specialized_arrmap(BDictN, {elem1,elem2}), { TStr, Type{BObj|BInt}, IterTypes::Count::NonEmpty, false, false } },
7006 { make_specialized_arrmap(BOptDictN, {elem1,elem2}), { TStr, Type{BObj|BInt}, IterTypes::Count::Any, true, false } },
7008 { make_specialized_arrmap(BDict, {elem1}, TInt, TInt), { union_of(sval(s_A),TInt), Type{BObj|BInt}, IterTypes::Count::Any, false, false } },
7009 { make_specialized_arrmap(BOptDict, {elem1}, TInt, TInt), { union_of(sval(s_A),TInt), Type{BObj|BInt}, IterTypes::Count::Any, true, false } },
7010 { make_specialized_arrmap(BDictN, {elem1}, TInt, TInt), { union_of(sval(s_A),TInt), Type{BObj|BInt}, IterTypes::Count::NonEmpty, false, false } },
7011 { make_specialized_arrmap(BOptDictN, {elem1}, TInt, TInt), { union_of(sval(s_A),TInt), Type{BObj|BInt}, IterTypes::Count::Any, true, false } },
7014 for (auto const& p : tests) {
7015 auto const iter = iter_types(p.first);
7016 EXPECT_EQ(iter.key, p.second.key);
7017 EXPECT_EQ(iter.value, p.second.value);
7018 EXPECT_EQ(iter.count, p.second.count) << show(p.first);
7019 EXPECT_EQ(iter.mayThrowOnInit, p.second.mayThrowOnInit);
7020 EXPECT_EQ(iter.mayThrowOnNext, p.second.mayThrowOnNext);
7024 //////////////////////////////////////////////////////////////////////