2 +----------------------------------------------------------------------+
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>
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
) {
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
);
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
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 {
201 .class [unique] A extends Base implements (IA) {
205 .class [no_override unique] AA extends A implements (IAA) {
209 .class [no_override unique] AB extends A {
213 .class [unique] B extends Base {
217 .class [unique] BA extends B {
221 .class [no_override unique] BB extends B {
225 .class [unique] BAA extends BA {
229 # Make sure BAA doesn't get AttrNoOverride:
230 .class [unique] BAADeriver extends BAA {
234 .class [unique] TestClass {
238 # Make sure TestClass doesn't get AttrNoOverride:
239 .class [unique] TestClassDeriver extends TestClass {
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 {
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) {
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) {
417 std::unique_ptr
<UnitEmitter
> ue(assemble_string(
418 hhas
.c_str(), hhas
.size(),
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
);
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
,
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
,
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
,
543 return {tv(s
), MapElem::StrKey(std::move(t
))};
545 std::pair
<TypedValue
, MapElem
> map_elem_counted(const StaticString
& s
,
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
)
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
});
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
);
594 // In the sense of "non-union type", not the sense of TPrim.
595 auto const primitives
= folly::lazy([]{
596 return std::vector
<Type
>{
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));
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
));
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
));
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
));
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
));
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
));
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
));
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
));
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
);
912 auto const specialized_arrays
= folly::lazy([]{
913 std::vector
<Type
> types
;
915 auto const add
= [&] (trep b
) {
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;
927 auto const keyBits
= [&containsUncounted
] (trep bits
) {
928 auto upper
= BBottom
;
929 auto lower
= BArrKey
;
931 if (couldBe(bits
, BVec
)) {
936 if (couldBe(bits
, BArrLikeN
)) {
937 if (subtypeOf(bits
, BSArrLikeN
)) {
942 lower
&= containsUncounted(bits
) ? BUncArrKey
: BArrKey
;
945 return std::make_pair(upper
, lower
);
948 auto const calcValBits
= [&containsUncounted
] (trep bits
, bool packed
) {
949 auto upper
= BBottom
;
950 auto lower
= BInitCell
;
952 if (couldBe(bits
, BKeysetN
)) {
956 } else if (subtypeAmong(bits
, BSKeysetN
, BKeysetN
)) {
965 if (couldBe(bits
, BArrLikeN
)) {
966 if (subtypeOf(bits
, BSArrLikeN
)) {
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
)) {
985 types
.emplace_back(make_specialized_arrpackedn(b
, t
));
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
});
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
));
1043 mapn(TUncArrKey
, TUncArrKey
);
1044 mapn(TArrKey
, TArrKey
);
1045 mapn(TUncArrKey
, TInt
);
1046 mapn(TUncArrKey
, TSStr
);
1047 mapn(TInt
, TUncArrKey
);
1048 mapn(TSStr
, TUncArrKey
);
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);
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
>{
1156 auto const subsetSize
= 1ULL << bits
.size();
1157 for (size_t i
= 0; i
< subsetSize
; ++i
) {
1159 for (size_t j
= 0; j
< bits
.size(); ++j
) {
1160 if (i
& (1ULL << j
)) b
|= bits
[j
];
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
);
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());
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
>{
1209 auto const subsetSize
= 1ULL << arrbits
.size();
1210 for (size_t i
= 0; i
< subsetSize
; ++i
) {
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
);
1225 //////////////////////////////////////////////////////////////////////
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
}));
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
)) {
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
);
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
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
);
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
}),
1337 dict_map({map_elem(5, t1
)}),
1340 const std::vector
<Type
> arrays2
{
1341 dict_packed({t2
, t2
}),
1343 dict_map({map_elem(5, t2
)}),
1346 for (auto const& a1
: arrays1
) {
1347 for (auto const& a2
: arrays2
) test(a1
, a2
, false);
1355 void test_basic_operators(const std::vector
<Type
>& types
) {
1356 for (auto const& t
: types
) {
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
)) {
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
);
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
)) {
1437 EXPECT_TRUE(t1
.subtypeOf(t2
));
1441 EXPECT_TRUE(t1
== t2
);
1444 EXPECT_TRUE(t1
.subtypeOf(t2
));
1446 if (t1
.strictlyMoreRefined(t2
)) {
1447 EXPECT_TRUE(t1
.strictSubtypeOf(t2
) || t1
== t2
);
1451 EXPECT_EQ(t1
== t2
, equivRefined
);
1452 EXPECT_EQ(t1
.subtypeOf(t2
), moreRefined
);
1453 EXPECT_EQ(t1
.strictSubtypeOf(t2
), t1
.strictlyMoreRefined(t2
));
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
));
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
));
1482 EXPECT_TRUE(uni
.equivalentlyRefined(t2
));
1483 EXPECT_TRUE(isect
.equivalentlyRefined(t1
));
1487 if (!is_specialized_array_like(t1
) && !is_specialized_array_like(t2
)) {
1488 EXPECT_FALSE(isect
.is(BBottom
));
1491 EXPECT_TRUE(isect
.is(BBottom
));
1494 if (!t1
.is(BBottom
)) {
1496 EXPECT_TRUE(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)); \
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);
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
)
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
)};
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());
1704 make_specialized_arrmapn(BVecN
|BKeysetN
, TArrKey
, TStr
),
1705 make_specialized_arrmapn(BDictN
|BKeysetN
, TInt
, TArrKey
)
1711 make_specialized_arrmapn(BArrLikeN
, TArrKey
, TStr
),
1712 make_specialized_arrmapn(BDictN
|BKeysetN
, TInt
, TArrKey
)
1714 make_specialized_arrmapn(BDictN
, TInt
, TStr
)
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
);
1738 make_specialized_arrpacked(BVecN
, {TStr
, TArrKey
, Type
{BInt
|BObj
}, TInitCell
}),
1741 make_specialized_arrpacked(BSVecN
, {TSStr
, TUncArrKey
, TInt
, TInitUnc
})
1745 make_specialized_arrpacked(BVecN
, {TStr
, TArrKey
, TObj
, TInitCell
}),
1753 make_specialized_arrpacked(BVecN
|BKeysetN
, {TArrKey
, TArrKey
}),
1756 make_specialized_arrpacked(BKeysetN
, {ival(0), ival(1)})
1761 make_specialized_arrpacked(BDictN
|BVecN
, {TObj
}),
1764 make_specialized_arrpacked(BVecN
, {TObj
})
1769 make_specialized_arrpacked(BSDictN
|BVecN
, {TInitCell
}),
1770 make_specialized_arrpacked(BCDictN
|BSVecN
, {TInitCell
})
1772 make_specialized_arrpacked(BSVecN
, {TInitUnc
})
1777 make_specialized_arrpackedn(BVecN
, TStr
),
1780 make_specialized_arrpackedn(BSVecN
, TSStr
)
1784 make_specialized_arrpackedn(BVecN
, TObj
),
1792 make_specialized_arrpackedn(BVecN
|BKeysetN
, TArrKey
),
1795 make_specialized_arrpackedn(BKeysetN
, TInt
)
1800 make_specialized_arrpackedn(BDictN
|BVecN
, TObj
),
1803 make_specialized_arrpackedn(BVecN
, TObj
)
1808 make_specialized_arrpackedn(BDictN
|BSVecN
, Type
{BInitCell
& ~BObj
}),
1809 make_specialized_arrpackedn(BSDictN
|BCVecN
, Type
{BInitCell
& ~BObj
})
1811 make_specialized_arrpackedn(BSDictN
, TInitUnc
)
1816 make_specialized_arrmapn(BDictN
|BVecN
, TArrKey
, TObj
),
1819 make_specialized_arrpackedn(BVecN
, TObj
)
1824 make_specialized_arrmapn(BDictN
, TArrKey
, TStr
),
1827 make_specialized_arrmapn(BSDictN
, TUncArrKey
, TSStr
)
1831 make_specialized_arrmapn(BDictN
, TArrKey
, TObj
),
1838 make_specialized_arrmapn(BDictN
, TCStr
, TStr
),
1846 make_specialized_arrmapn(BDictN
|BKeysetN
, TStr
, TArrKey
),
1847 make_specialized_arrmapn(BVecN
|BKeysetN
, TArrKey
, TArrKey
)
1849 make_specialized_arrmapn(BKeysetN
, TStr
, TStr
)
1853 make_specialized_arrmapn(BDictN
|BKeysetN
, TStr
, TArrKey
),
1854 make_specialized_arrmapn(BVecN
|BKeysetN
, TArrKey
, TInt
)
1861 make_specialized_arrmapn(BDictN
|BKeysetN
, TStr
, TArrKey
),
1862 make_specialized_arrmapn(BDictN
|BKeysetN
, TArrKey
, TInt
)
1864 make_specialized_arrmapn(BDictN
, TStr
, TInt
)
1869 make_specialized_arrmapn(BDictN
|BCKeysetN
, TCStr
, TCStr
),
1870 Type
{BDictN
|BSKeysetN
}
1872 make_specialized_arrmapn(BDictN
, TCStr
, TCStr
)
1877 make_specialized_arrmapn(BDictN
|BKeysetN
, TArrKey
, Type
{BInitCell
& ~BObj
}),
1878 make_specialized_arrmapn(BSDictN
|BVecN
, TUncArrKey
, Type
{BInitCell
& ~BObj
})
1884 make_specialized_arrmapn(BCDictN
|BSVecN
, TArrKey
, Type
{BInitCell
& ~BObj
}),
1885 make_specialized_arrmapn(BSDictN
|BVecN
, TUncArrKey
, Type
{BInitCell
& ~BObj
})
1892 make_specialized_arrmap(BDictN
, {map_elem(s_A
, TStr
)}),
1895 make_specialized_arrmap(BSDictN
, {map_elem(s_A
, TSStr
)})
1899 make_specialized_arrmap(BDictN
, {map_elem_nonstatic(s_A
, TStr
)}),
1902 make_specialized_arrmap(BSDictN
, {map_elem(s_A
, TSStr
)})
1906 make_specialized_arrmap(BDictN
, {map_elem_counted(s_A
, TStr
)}),
1913 make_specialized_arrmap(BDictN
, {map_elem(123, TStr
)}),
1916 make_specialized_arrmap(BSDictN
, {map_elem(123, TSStr
)})
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
))})
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
))})
1935 make_specialized_arrmap(BSDictN
|BKeysetN
, {map_elem(s_A
, TArrKey
)}),
1936 make_specialized_arrmap(BCDictN
|BKeysetN
, {map_elem_nonstatic(s_A
, TCStr
)})
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
)})
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
)})
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
)
1966 make_specialized_arrpackedn(BVecN
|BKeysetN
, ival(0)),
1969 make_specialized_arrpacked(BKeysetN
, {ival(0)})
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
));
1987 EXPECT_EQ(split
, TBottom
);
1989 EXPECT_FALSE(rest
.couldBe(bits
));
1990 if (orig
.subtypeOf(bits
)) {
1991 EXPECT_EQ(rest
, TBottom
);
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());
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
,
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());
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
);
2255 const std::initializer_list
<std::pair
<Type
, Type
>> subtype_true
{
2259 { TInitNull
, TPrim
},
2261 { dval(0.0), 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
},
2276 { TNull
, TInitPrim
}, // TNull could be uninit
2280 { TInitPrim
, TNum
},
2282 { TUnc
, TInitPrim
},
2283 { TInitUnc
, TPrim
},
2284 { TSStr
, TInitPrim
},
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
{
2298 { TInitPrim
, TNum
},
2299 { TInitPrim
, TFalse
},
2302 { TPrim
, TOptFalse
},
2305 const std::initializer_list
<std::pair
<Type
, Type
>> couldbe_false
{
2307 { TInitPrim
, TSStr
},
2308 { TInitPrim
, sval(s_test
) },
2309 { TInitPrim
, lazyclsval(s_test
) },
2310 { TPrim
, sval(s_test
) },
2311 { TInitPrim
, TUninit
},
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
)));
2361 sval_nonstatic(s_test
).couldBe(sval_nonstatic(s_A
))
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
)));
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
);
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
));
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
);
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
);
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
));
2561 union_of(opt(sval(s_test
)), opt(sval(s_TestClass
))));
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
);
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))));
2671 make_specialized_arrmap(
2673 {map_elem(s_A
, ival(1)), map_elem(s_B
, ival(2))},
2675 LegacyMark::Unmarked
2677 make_array_like_tv(const_cast<ArrayData
*>(static_dict(s_A
.get(), 1, s_B
.get(), 2)))
2680 make_specialized_arrmap(
2682 {map_elem_nonstatic(s_A
, ival(1)), map_elem_nonstatic(s_B
, ival(2))},
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());
2698 make_specialized_arrmap(
2700 {map_elem(s_A
, ival(1)), map_elem(s_B
, ival(2))},
2702 LegacyMark::Unmarked
2708 make_specialized_arrmap(
2710 {map_elem_counted(s_A
, ival(1)), map_elem_counted(s_B
, ival(2))},
2712 LegacyMark::Unmarked
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());
2724 make_specialized_arrmap(
2726 {map_elem(s_A
, ival(1)), map_elem(s_B
, ival(2))},
2728 LegacyMark::Unmarked
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());
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
));
2783 make_unmarked(make_specialized_arrpacked(BVecN
, {sval_counted(s_A
)})),
2784 make_array_like_tv(const_cast<ArrayData
*>(static_vec(s_A
.get())))
2787 make_unmarked(make_specialized_arrpacked(BCVecN
, {sval(s_A
)})),
2788 make_array_like_tv(const_cast<ArrayData
*>(static_vec(s_A
.get())))
2791 make_specialized_arrmap(
2793 {map_elem_counted(s_A
, ival(1)), map_elem_counted(s_B
, ival(2))},
2795 LegacyMark::Unmarked
2797 make_array_like_tv(const_cast<ArrayData
*>(static_dict(s_A
.get(), 1, s_B
.get(), 2)))
2800 make_specialized_arrmap(
2802 {map_elem(s_A
, ival(1)), map_elem(s_B
, ival(2))},
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
{
2908 sval_nonstatic(s_A
),
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
);
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
{
3290 ival(std::numeric_limits
<int64_t>::max()),
3294 sval_nonstatic(s_A
),
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
);
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
),
3355 auto const mapElem2
= MapElems
{
3356 map_elem(s_A
, TInt
),
3357 map_elem(100, TObj
),
3358 map_elem(s_B
, TFalse
),
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
),
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
)),
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
{
3613 sval_nonstatic(s_A
),
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
{
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
);
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
{
3687 auto const mapElem2
= MapElems
{
3688 map_elem_nonstatic(s_A
, TObj
)
3690 auto const mapElem3
= MapElems
{
3691 map_elem(int64_t(0), TInt
),
3693 map_elem(s_A
, TFalse
)
3695 auto const mapElem4
= MapElems
{
3696 map_elem(int64_t(0), TInt
),
3699 auto const mapElem5
= MapElems
{
3700 map_elem(int64_t(0), TInt
),
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
{
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
{
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
>{
3952 dict_packed({TDbl
}),
3953 dict_packed({TBool
}),
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();
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();
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
)));
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
);
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
);
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();
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
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();
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
));
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
));
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
);
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
)));
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
)));
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
)));
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
));
4651 if (t
.strictSubtypeOf(BInitCell
)) {
4652 EXPECT_TRUE(is_specialized_wait_handle(u1
));
4653 EXPECT_TRUE(is_specialized_wait_handle(u2
));
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
);
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
));
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
));
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
));
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
));
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
));
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
);
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
));
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));
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
);
5118 intersection_of(dict_n(TArrKey
, TObj
), TSDictN
),
5122 intersection_of(union_of(dict_n(TInt
, TObj
), TDictE
),
5123 union_of(dict_packed({TInt
, TObj
}), TDictE
)),
5127 intersection_of(opt(dict_n(TInt
, TObj
)), TUnc
),
5131 intersection_of(opt(dict_packedn(TObj
)), TInitUnc
),
5135 intersection_of(union_of(dict_packed({TInt
, TObj
}), TDictE
), TUnc
),
5139 intersection_of(opt(union_of(dict_packed({TInt
, TObj
}), TDictE
)), TUnc
),
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
));
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
);
5267 loosen_staticness(t
),
5269 loosen_staticness(obj
),
5270 loosen_staticness(str
),
5271 loosen_staticness(arr
),
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
= {
5329 { TSDictE
, TDictE
},
5330 { TSDictN
, TDictN
},
5335 { TSDictE
, TDictE
},
5336 { TSDictN
, TDictN
},
5338 { TSKeysetE
, TKeysetE
},
5339 { TSKeysetN
, TKeysetN
},
5340 { TSKeyset
, TKeyset
},
5341 { TUncArrKey
, TArrKey
},
5343 Type
{BInitNull
|BArrLike
|BArrKey
|BBool
|BCls
|BDbl
|BFunc
|BLazyCls
|BClsMeth
|BUninit
} },
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
},
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
);
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
);
5392 loosen_string_staticness(t
),
5393 union_of(loosen_string_staticness(str
), rest
)
5397 const std::vector
<std::pair
<Type
, Type
>> tests
= {
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
},
5409 { TSArrLike
, TSArrLike
},
5410 { TCArrLike
, TCArrLike
},
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
);
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
);
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
= {
5482 { TSDictE
, TDictE
},
5483 { TSDictN
, TDictN
},
5488 { TSDictE
, TDictE
},
5489 { TSDictN
, TDictN
},
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
},
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
);
5580 case Emptiness::Maybe
:
5581 EXPECT_NE(emptiness(assert_nonemptiness(t
)), Emptiness::Empty
);
5583 case Emptiness::NonEmpty
:
5584 EXPECT_EQ(assert_nonemptiness(t
), t
);
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
},
5606 { TDictE
, TBottom
},
5609 { TArrLikeE
, TBottom
},
5610 { TArrLikeN
, TArrLikeN
},
5611 { TArrLike
, TArrLikeN
},
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
)} },
5627 { TLazyCls
, TLazyCls
},
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
);
5650 case Emptiness::Maybe
:
5651 EXPECT_NE(emptiness(assert_emptiness(t
)), Emptiness::NonEmpty
);
5653 case Emptiness::NonEmpty
:
5654 EXPECT_EQ(assert_emptiness(t
), TBottom
);
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
},
5672 { TDictN
, TBottom
},
5674 { TArrLikeE
, TArrLikeE
},
5675 { TArrLikeN
, TBottom
},
5676 { TArrLike
, TArrLikeE
},
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
},
5693 { TStr
, sempty_nonstatic() },
5694 { TSStr
, sempty() },
5695 { TLazyCls
, TBottom
},
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
);
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
);
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
= {
5739 { TSDictE
, TSDict
},
5740 { TSDictN
, TSDict
},
5743 { TSKeysetE
, TSKeyset
},
5744 { TSKeysetN
, TSKeyset
},
5745 { TKeysetE
, TKeyset
},
5746 { TKeysetN
, TKeyset
},
5751 { TSDictE
, TSDict
},
5752 { TSDictN
, TSDict
},
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();
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
);
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());
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
);
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
);
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
= {
5915 { TSDictE
, TSDict
},
5917 { TSDictN
, TSDictN
},
5918 { TKeysetE
, TKeyset
},
5919 { TSKeysetE
, TSKeyset
},
5920 { TKeysetN
, TKeysetN
},
5921 { TSKeysetN
, TSKeysetN
},
5927 { TSDictE
, TSDict
},
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
},
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
);
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
);
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
},
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
},
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
));
6155 dict_map(test_map_c
, TSStr
, TInt
).subtypeOf(dict_map(test_map_d
, TSStr
, TInt
))
6158 dict_map(test_map_a
, TSStr
, TInt
).subtypeOf(dict_map(test_map_e
, TSStr
, TInt
))
6161 dict_map(test_map_b
, TSStr
, TInt
).subtypeOf(dict_map(test_map_a
, TSStr
, TInt
))
6164 dict_map(test_map_a
, TSStr
, TInt
).subtypeOf(dict_map(test_map_b
, TSStr
, TInt
))
6167 sdict_map(test_map_a
, TSStr
, TInt
).subtypeOf(sdict_map(test_map_b
, TSStr
, TNum
))
6170 dict_map(test_map_a
, TSStr
, TInt
).subtypeOf(dict_map(test_map_b
, TInt
, TNum
))
6173 dict_map(test_map_a
, TSStr
, TInt
).subtypeOf(dict_map(test_map_a
, TStr
, TInt
))
6176 dict_map(test_map_a
, TStr
, TInt
).subtypeOf(dict_map(test_map_a
, TSStr
, TInt
))
6179 dict_map(test_map_a
, TSStr
, TNum
).subtypeOf(dict_map(test_map_a
, TSStr
, TInt
))
6182 dict_map(test_map_a
, TSStr
, TInt
).subtypeOf(dict_n(TStr
, TNum
))
6185 dict_map(test_map_a
, TSStr
, TInt
).subtypeOf(dict_n(TStr
, TInt
))
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
)));
6192 dict_n(TSStr
, TInt
).subtypeOf(dict_map(test_map_a
, TSStr
, TInt
))
6196 dict_map(test_map_a
, TSStr
, TInt
).couldBe(dict_map(test_map_a
, TSStr
, TInt
))
6199 dict_map(test_map_a
, TSStr
, TInt
).couldBe(dict_map(test_map_a
, TSStr
, TNum
))
6202 dict_map(test_map_a
, TSStr
, TNum
).couldBe(dict_map(test_map_a
, TSStr
, TInt
))
6205 dict_map(test_map_a
, TArrKey
, TInt
).couldBe(dict_map(test_map_a
, TSStr
, TInt
))
6208 dict_map(test_map_a
, TSStr
, TInt
).couldBe(dict_map(test_map_a
, TArrKey
, TInt
))
6211 dict_map(test_map_a
, TSStr
, TInt
).couldBe(dict_map(test_map_a
, TInt
, TInt
))
6214 dict_map(test_map_a
, TInt
, TInt
).couldBe(dict_map(test_map_a
, TSStr
, TInt
))
6217 dict_map(test_map_a
, TSStr
, TDbl
).couldBe(dict_map(test_map_a
, TSStr
, TObj
))
6220 dict_map(test_map_a
, TSStr
, TInt
).couldBe(dict_map(test_map_c
, TSStr
, TInt
))
6223 dict_map(test_map_c
, TSStr
, TInt
).couldBe(dict_map(test_map_a
, TSStr
, TInt
))
6226 dict_map(test_map_a
, TSStr
, TInt
).couldBe(dict_map(test_map_e
, TSStr
, TInt
))
6229 dict_map(test_map_e
, TSStr
, TInt
).couldBe(dict_map(test_map_a
, TSStr
, TInt
))
6232 dict_map(test_map_a
).couldBe(dict_map(test_map_b
, TSStr
, TDbl
))
6235 dict_map(test_map_b
, TSStr
, TDbl
).couldBe(dict_map(test_map_a
))
6238 dict_map(test_map_a
).couldBe(dict_map(test_map_b
, TSStr
, TObj
))
6241 dict_map(test_map_b
, TSStr
, TObj
).couldBe(dict_map(test_map_a
))
6245 union_of(sdict_map(test_map_a
), sdict_map(test_map_b
)),
6246 sdict_map(test_map_b
, sval(s_B
), TDbl
)
6249 union_of(sdict_map(test_map_a
), sdict_map(test_map_c
)),
6250 sdict_map(test_map_b
, TSStr
, TNum
)
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
)
6257 union_of(dict_map(test_map_c
), dict_map(test_map_d
)),
6261 union_of(dict_map(test_map_c
, TInt
, TInt
), dict_map(test_map_d
, TInt
, TInt
)),
6262 dict_n(TUncArrKey
, TInt
)
6266 dict_map(test_map_c
, TSStr
, TDbl
),
6267 dict_map(test_map_d
, TSStr
, TDbl
)
6272 union_of(dict_map(test_map_c
, TSStr
, TDbl
), dict_packed({TInt
})),
6273 dict_n(union_of(ival(0),TSStr
), TNum
)
6276 union_of(sdict_map(test_map_c
, TSStr
, TDbl
), sdict_packedn(TInt
)),
6277 sdict_n(TUncArrKey
, TNum
)
6280 union_of(dict_map(test_map_c
, TInt
, TDbl
), dict_n(TSStr
, TInt
)),
6281 dict_n(TUncArrKey
, TNum
)
6286 dict_map(test_map_a
, TSStr
, TInt
),
6287 dict_map(test_map_a
, TSStr
, TInt
)
6289 dict_map(test_map_a
, TSStr
, TInt
)
6293 dict_map(test_map_a
, TSStr
, TArrKey
),
6294 dict_map(test_map_a
, TSStr
, TInt
)
6296 dict_map(test_map_a
, TSStr
, TInt
)
6300 dict_map(test_map_a
, TSStr
, TInt
),
6301 dict_map(test_map_a
, TArrKey
, TInt
)
6303 dict_map(test_map_a
, TSStr
, TInt
)
6307 dict_map(test_map_a
, TSStr
, TInt
),
6308 dict_map(test_map_a
, TInt
, TInt
)
6310 dict_map(test_map_a
)
6314 dict_map(test_map_a
, TInt
, TStr
),
6315 dict_map(test_map_a
, TInt
, TInt
)
6317 dict_map(test_map_a
)
6321 dict_map(test_map_a
, TInt
, TInt
),
6322 dict_map(test_map_e
, TInt
, TInt
)
6327 intersection_of(dict_map(test_map_a
), dict_map(test_map_b
, TSStr
, TNum
)),
6328 dict_map(test_map_a
)
6331 intersection_of(dict_map(test_map_b
, TSStr
, TNum
), dict_map(test_map_a
)),
6332 dict_map(test_map_a
)
6335 intersection_of(dict_map(test_map_a
), dict_map(test_map_b
, TSStr
, TObj
)),
6339 intersection_of(dict_map(test_map_b
, TSStr
, TObj
), dict_map(test_map_a
)),
6343 intersection_of(dict_map(test_map_a
, TSStr
, TObj
), dict_n(TSStr
, TObj
)),
6347 intersection_of(dict_map(test_map_a
, TSStr
, TObj
), dict_n(TSStr
, TNum
)),
6348 dict_map(test_map_a
)
6352 dict_map(test_map_a
, TSStr
, TInitCell
),
6355 dict_map(test_map_a
, TSStr
, TNum
)
6359 array_like_set(dict_map(test_map_b
), TSStr
, TStr
).first
,
6360 dict_map(test_map_g
, TSStr
, TStr
)
6363 array_like_set(dict_map(test_map_a
), sval(s_B
), TStr
).first
,
6364 dict_map(test_map_h
)
6367 array_like_set(dict_map(test_map_a
), sval(s_test
), TStr
).first
,
6368 dict_map(test_map_i
)
6371 array_like_set(dict_map(test_map_a
, TSStr
, TInt
), sval(s_test
), TStr
).first
,
6372 dict_map(test_map_a
, TSStr
, TArrKey
)
6376 dict_map(test_map_a
, sval(s_test
), TInt
),
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();
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();
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
),
6448 REFINE_EQ(return_with_context(subObjBaseTy
, objExactBTy
),
6450 REFINE_EQ(return_with_context(objExactBTy
, objExactBTy
),
6452 REFINE_EQ(return_with_context(subObjBTy
, objExactBTy
),
6454 REFINE_EQ(return_with_context(objExactBBTy
, objExactBTy
),
6456 REFINE_EQ(return_with_context(subObjBBTy
, objExactBTy
),
6458 REFINE_EQ(return_with_context(objExactUnTy
, objExactBTy
),
6460 REFINE_EQ(return_with_context(subObjUnTy
, objExactBTy
),
6462 REFINE_EQ(return_with_context(objExactBaseTy
, clsExactBTy
),
6464 REFINE_EQ(return_with_context(subObjBaseTy
, clsExactBTy
),
6466 REFINE_EQ(return_with_context(objExactBTy
, clsExactBTy
),
6468 REFINE_EQ(return_with_context(subObjBTy
, clsExactBTy
),
6470 REFINE_EQ(return_with_context(objExactBBTy
, clsExactBTy
),
6472 REFINE_EQ(return_with_context(subObjBBTy
, clsExactBTy
),
6474 REFINE_EQ(return_with_context(objExactUnTy
, clsExactBTy
),
6476 REFINE_EQ(return_with_context(subObjUnTy
, clsExactBTy
),
6480 REFINE_EQ(return_with_context(objExactBaseTy
, subObjBTy
),
6482 REFINE_EQ(return_with_context(subObjBaseTy
, subObjBTy
),
6484 REFINE_EQ(return_with_context(objExactBTy
, subObjBTy
),
6486 REFINE_EQ(return_with_context(subObjBTy
, subObjBTy
),
6488 REFINE_EQ(return_with_context(objExactBBTy
, subObjBTy
),
6490 REFINE_EQ(return_with_context(subObjBBTy
, subObjBTy
),
6492 REFINE_EQ(return_with_context(objExactUnTy
, subObjBTy
),
6494 REFINE_EQ(return_with_context(subObjUnTy
, subObjBTy
),
6496 REFINE_EQ(return_with_context(objExactBaseTy
, subClsBTy
),
6498 REFINE_EQ(return_with_context(subObjBaseTy
, subClsBTy
),
6500 REFINE_EQ(return_with_context(objExactBTy
, subClsBTy
),
6502 REFINE_EQ(return_with_context(subObjBTy
, subClsBTy
),
6504 REFINE_EQ(return_with_context(objExactBBTy
, subClsBTy
),
6506 REFINE_EQ(return_with_context(subObjBBTy
, subClsBTy
),
6508 REFINE_EQ(return_with_context(objExactUnTy
, subClsBTy
),
6510 REFINE_EQ(return_with_context(subObjUnTy
, subClsBTy
),
6513 // Improvements (exact)
6514 REFINE_EQ(return_with_context(thisObjExactBaseTy
, objExactBTy
),
6516 REFINE_EQ(return_with_context(thisSubObjBaseTy
, objExactBTy
),
6518 REFINE_EQ(return_with_context(thisObjExactBTy
, objExactBTy
),
6520 REFINE_EQ(return_with_context(thisSubObjBTy
, objExactBTy
),
6522 REFINE_EQ(return_with_context(thisObjExactBBTy
, objExactBTy
),
6524 REFINE_EQ(return_with_context(thisSubObjBBTy
, objExactBTy
),
6526 REFINE_EQ(return_with_context(thisObjExactUnTy
, objExactBTy
),
6528 REFINE_EQ(return_with_context(thisSubObjUnTy
, objExactBTy
),
6530 REFINE_EQ(return_with_context(thisObjExactBaseTy
, clsExactBTy
),
6532 REFINE_EQ(return_with_context(thisSubObjBaseTy
, clsExactBTy
),
6534 REFINE_EQ(return_with_context(thisObjExactBTy
, clsExactBTy
),
6536 REFINE_EQ(return_with_context(thisSubObjBTy
, clsExactBTy
),
6538 REFINE_EQ(return_with_context(thisObjExactBBTy
, clsExactBTy
),
6540 REFINE_EQ(return_with_context(thisSubObjBBTy
, clsExactBTy
),
6542 REFINE_EQ(return_with_context(thisObjExactUnTy
, clsExactBTy
),
6544 REFINE_EQ(return_with_context(thisSubObjUnTy
, clsExactBTy
),
6546 REFINE_EQ(return_with_context(thisObjExactBaseTy
, thisObjExactBTy
),
6548 REFINE_EQ(return_with_context(thisSubObjBaseTy
, thisObjExactBTy
),
6550 REFINE_EQ(return_with_context(thisObjExactBTy
, thisObjExactBTy
),
6552 REFINE_EQ(return_with_context(thisSubObjBTy
, thisObjExactBTy
),
6554 REFINE_EQ(return_with_context(thisObjExactBBTy
, thisObjExactBTy
),
6556 REFINE_EQ(return_with_context(thisSubObjBBTy
, thisObjExactBTy
),
6558 REFINE_EQ(return_with_context(thisObjExactUnTy
, thisObjExactBTy
),
6560 REFINE_EQ(return_with_context(thisSubObjUnTy
, thisObjExactBTy
),
6562 REFINE_EQ(return_with_context(thisObjExactBaseTy
, thisClsExactBTy
),
6564 REFINE_EQ(return_with_context(thisSubObjBaseTy
, thisClsExactBTy
),
6566 REFINE_EQ(return_with_context(thisObjExactBTy
, thisClsExactBTy
),
6568 REFINE_EQ(return_with_context(thisSubObjBTy
, thisClsExactBTy
),
6570 REFINE_EQ(return_with_context(thisObjExactBBTy
, thisClsExactBTy
),
6572 REFINE_EQ(return_with_context(thisSubObjBBTy
, thisClsExactBTy
),
6574 REFINE_EQ(return_with_context(thisObjExactUnTy
, thisClsExactBTy
),
6576 REFINE_EQ(return_with_context(thisSubObjUnTy
, thisClsExactBTy
),
6579 // Improvements (sub)
6580 REFINE_EQ(return_with_context(thisObjExactBaseTy
, subObjBTy
),
6582 REFINE_EQ(return_with_context(thisSubObjBaseTy
, subObjBTy
),
6584 REFINE_EQ(return_with_context(thisObjExactBTy
, subObjBTy
),
6586 REFINE_EQ(return_with_context(thisSubObjBTy
, subObjBTy
),
6588 REFINE_EQ(return_with_context(thisObjExactBBTy
, subObjBTy
),
6590 REFINE_EQ(return_with_context(thisSubObjBBTy
, subObjBTy
),
6592 REFINE_EQ(return_with_context(thisObjExactUnTy
, subObjBTy
),
6594 REFINE_EQ(return_with_context(thisSubObjUnTy
, subObjBTy
),
6596 REFINE_EQ(return_with_context(thisObjExactBaseTy
, subClsBTy
),
6598 REFINE_EQ(return_with_context(thisSubObjBaseTy
, subClsBTy
),
6600 REFINE_EQ(return_with_context(thisObjExactBTy
, subClsBTy
),
6602 REFINE_EQ(return_with_context(thisSubObjBTy
, subClsBTy
),
6604 REFINE_EQ(return_with_context(thisObjExactBBTy
, subClsBTy
),
6606 REFINE_EQ(return_with_context(thisSubObjBBTy
, subClsBTy
),
6608 REFINE_EQ(return_with_context(thisObjExactUnTy
, subClsBTy
),
6610 REFINE_EQ(return_with_context(thisSubObjUnTy
, subClsBTy
),
6612 REFINE_EQ(return_with_context(thisObjExactBaseTy
, thisSubObjBTy
),
6614 REFINE_EQ(return_with_context(thisSubObjBaseTy
, thisSubObjBTy
),
6616 REFINE_EQ(return_with_context(thisObjExactBTy
, thisSubObjBTy
),
6618 REFINE_EQ(return_with_context(thisSubObjBTy
, thisSubObjBTy
),
6620 REFINE_EQ(return_with_context(thisObjExactBBTy
, thisSubObjBTy
),
6622 REFINE_EQ(return_with_context(thisSubObjBBTy
, thisSubObjBTy
),
6624 REFINE_EQ(return_with_context(thisObjExactUnTy
, thisSubObjBTy
),
6626 REFINE_EQ(return_with_context(thisSubObjUnTy
, thisSubObjBTy
),
6628 REFINE_EQ(return_with_context(thisObjExactBaseTy
, thisSubClsBTy
),
6630 REFINE_EQ(return_with_context(thisSubObjBaseTy
, thisSubClsBTy
),
6632 REFINE_EQ(return_with_context(thisObjExactBTy
, thisSubClsBTy
),
6634 REFINE_EQ(return_with_context(thisSubObjBTy
, thisSubClsBTy
),
6636 REFINE_EQ(return_with_context(thisObjExactBBTy
, thisSubClsBTy
),
6638 REFINE_EQ(return_with_context(thisSubObjBBTy
, thisSubClsBTy
),
6640 REFINE_EQ(return_with_context(thisObjExactUnTy
, thisSubClsBTy
),
6642 REFINE_EQ(return_with_context(thisSubObjUnTy
, thisSubClsBTy
),
6645 // Optional type preservation.
6646 REFINE_EQ(return_with_context(opt(subObjBaseTy
), objExactBTy
),
6648 REFINE_EQ(return_with_context(opt(subObjBaseTy
), clsExactBTy
),
6650 REFINE_EQ(return_with_context(opt(subObjBaseTy
), subObjBTy
),
6652 REFINE_EQ(return_with_context(opt(subObjBaseTy
), subClsBTy
),
6654 REFINE_EQ(return_with_context(opt(thisSubObjBaseTy
), objExactBTy
),
6656 REFINE_EQ(return_with_context(opt(thisSubObjBaseTy
), clsExactBTy
),
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
);
6735 return_with_context(t
, context
),
6737 return_with_context(obj
, context
),
6738 return_with_context(cls
, context
),
6748 test(thisObjExactBTy
);
6749 test(thisClsExactBTy
);
6750 test(thisSubObjBTy
);
6751 test(thisSubClsBTy
);
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
},
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
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
);
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
} },
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
)));
6852 loosen_likeness_recursively(wait_handle(index
, t
)),
6853 wait_handle(index
, loosen_likeness_recursively(t
)));
6855 loosen_likeness_recursively(vec_n(t
)),
6856 vec_n(loosen_likeness_recursively(t
)));
6858 loosen_likeness_recursively(vec({t
})),
6859 vec({loosen_likeness_recursively(t
)}));
6861 loosen_likeness_recursively(dict_n(TArrKey
, t
)),
6862 dict_n(TArrKey
, loosen_likeness_recursively(t
)));
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;
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
);
6884 std::vector
<std::pair
<Type
, Type
>> tests
{
6885 { TClsMeth
, Type
{BClsMeth
} },
6886 { TCls
, Type
{BCls
|BSStr
} },
6887 { TLazyCls
, Type
{BLazyCls
|BSStr
} },
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 //////////////////////////////////////////////////////////////////////