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 +----------------------------------------------------------------------+
17 #include <unordered_set>
19 #include <folly/portability/GTest.h>
20 #include <folly/ScopeGuard.h>
22 #include "hphp/runtime/base/array-data.h"
23 #include "hphp/runtime/base/array-init.h"
24 #include "hphp/runtime/base/repo-auth-type-array.h"
25 #include "hphp/runtime/test/bespoke-layout-mock.h"
26 #include "hphp/runtime/vm/jit/array-layout.h"
27 #include "hphp/runtime/vm/jit/guard-constraint.h"
28 #include "hphp/runtime/vm/jit/print.h"
29 #include "hphp/runtime/vm/jit/type.h"
31 // for specialized object tests to get some real VM::Class
32 #include "hphp/system/systemlib.h"
35 namespace HPHP
{ namespace jit
{
39 std::unordered_set
<Type
> allTypes() {
40 std::unordered_set
<Type
> r
;
41 #define IRT(name, ...) r.insert(T##name);
42 #define IRTP(name, ...) IRT(name)
43 #define IRTL(name, ...) IRT(name)
44 #define IRTM(name, ...) IRT(name)
45 #define IRTX(name, ...) IRT(name)
57 TEST(Type
, Equality
) {
58 EXPECT_NE(TCls
, TPtrToObj
);
59 EXPECT_NE(TLazyCls
, TPtrToObj
);
60 EXPECT_NE(TCls
, TLvalToObj
);
61 EXPECT_NE(TLazyCls
, TLvalToObj
);
62 EXPECT_NE(TCls
, TMemToObj
);
63 EXPECT_NE(TLazyCls
, TMemToObj
);
67 EXPECT_TRUE(TUninit
<= TNull
);
68 EXPECT_TRUE(TInitNull
<= TNull
);
69 EXPECT_FALSE(TBool
<= TNull
);
70 EXPECT_FALSE(TNull
<= TInitNull
);
71 EXPECT_NE(TNull
, TUninit
);
72 EXPECT_NE(TNull
, TInitNull
);
74 EXPECT_TRUE(TNull
.needsReg());
75 EXPECT_FALSE(TUninit
.needsReg());
76 EXPECT_FALSE(TInitNull
.needsReg());
79 TEST(Type
, KnownDataType
) {
105 for (auto t
: trueTypes
) {
106 EXPECT_TRUE(t
.isKnownDataType())
107 << t
.toString() << ".isKnownDataType()";
116 for (auto t
: falseTypes
) {
117 EXPECT_FALSE(t
.isKnownDataType())
118 << "!" << t
.toString() << ".isKnownDataType()";
122 TEST(Type
, ArrayLayout
) {
123 auto const top
= ArrayLayout::Top();
124 auto const vanilla
= ArrayLayout::Vanilla();
125 auto const bespoke
= ArrayLayout::Bespoke();
126 auto const bottom
= ArrayLayout::Bottom();
127 auto const foo
= ArrayLayout
{
128 bespoke::testing::makeDummyLayout("foo", {ArrayLayout::Bespoke()})
131 EXPECT_EQ("Top", top
.describe());
132 EXPECT_EQ("Vanilla", vanilla
.describe());
133 EXPECT_EQ("Bespoke", bespoke
.describe());
134 EXPECT_EQ("Bottom", bottom
.describe());
135 EXPECT_EQ("foo", foo
.describe());
138 EXPECT_EQ(vanilla
, vanilla
);
139 EXPECT_EQ(bespoke
, bespoke
);
140 EXPECT_EQ(bottom
, bottom
);
143 EXPECT_NE(top
, vanilla
);
144 EXPECT_NE(top
, bespoke
);
145 EXPECT_NE(top
, bottom
);
147 EXPECT_NE(vanilla
, bespoke
);
148 EXPECT_NE(vanilla
, bottom
);
149 EXPECT_NE(vanilla
, foo
);
150 EXPECT_NE(bespoke
, bottom
);
151 EXPECT_NE(bespoke
, foo
);
152 EXPECT_NE(bottom
, foo
);
154 EXPECT_TRUE(top
<= top
);
155 EXPECT_FALSE(top
<= vanilla
);
156 EXPECT_FALSE(top
<= bespoke
);
157 EXPECT_FALSE(top
<= bottom
);
158 EXPECT_FALSE(top
<= foo
);
159 EXPECT_TRUE(vanilla
<= top
);
160 EXPECT_TRUE(vanilla
<= vanilla
);
161 EXPECT_FALSE(vanilla
<= bespoke
);
162 EXPECT_FALSE(vanilla
<= bottom
);
163 EXPECT_FALSE(vanilla
<= foo
);
164 EXPECT_TRUE(bespoke
<= top
);
165 EXPECT_FALSE(bespoke
<= vanilla
);
166 EXPECT_TRUE(bespoke
<= bespoke
);
167 EXPECT_FALSE(bespoke
<= bottom
);
168 EXPECT_FALSE(bespoke
<= foo
);
169 EXPECT_TRUE(bottom
<= top
);
170 EXPECT_TRUE(bottom
<= vanilla
);
171 EXPECT_TRUE(bottom
<= bespoke
);
172 EXPECT_TRUE(bottom
<= bottom
);
173 EXPECT_TRUE(bottom
<= foo
);
174 EXPECT_TRUE(foo
<= top
);
175 EXPECT_FALSE(foo
<= vanilla
);
176 EXPECT_TRUE(foo
<= bespoke
);
177 EXPECT_FALSE(foo
<= bottom
);
178 EXPECT_TRUE(foo
<= foo
);
180 EXPECT_EQ(top
| top
, top
);
181 EXPECT_EQ(top
| vanilla
, top
);
182 EXPECT_EQ(top
| bespoke
, top
);
183 EXPECT_EQ(top
| bottom
, top
);
184 EXPECT_EQ(top
| foo
, top
);
185 EXPECT_EQ(vanilla
| top
, top
);
186 EXPECT_EQ(vanilla
| vanilla
, vanilla
);
187 EXPECT_EQ(vanilla
| bespoke
, top
);
188 EXPECT_EQ(vanilla
| bottom
, vanilla
);
189 EXPECT_EQ(vanilla
| foo
, top
);
190 EXPECT_EQ(bespoke
| top
, top
);
191 EXPECT_EQ(bespoke
| vanilla
, top
);
192 EXPECT_EQ(bespoke
| bespoke
, bespoke
);
193 EXPECT_EQ(bespoke
| bottom
, bespoke
);
194 EXPECT_EQ(bespoke
| foo
, bespoke
);
195 EXPECT_EQ(bottom
| top
, top
);
196 EXPECT_EQ(bottom
| vanilla
, vanilla
);
197 EXPECT_EQ(bottom
| bespoke
, bespoke
);
198 EXPECT_EQ(bottom
| bottom
, bottom
);
199 EXPECT_EQ(bottom
| foo
, foo
);
200 EXPECT_EQ(foo
| top
, top
);
201 EXPECT_EQ(foo
| vanilla
, top
);
202 EXPECT_EQ(foo
| bespoke
, bespoke
);
203 EXPECT_EQ(foo
| bottom
, foo
);
204 EXPECT_EQ(foo
| foo
, foo
);
206 EXPECT_EQ(top
& top
, top
);
207 EXPECT_EQ(top
& vanilla
, vanilla
);
208 EXPECT_EQ(top
& bespoke
, bespoke
);
209 EXPECT_EQ(top
& bottom
, bottom
);
210 EXPECT_EQ(top
& foo
, foo
);
211 EXPECT_EQ(vanilla
& top
, vanilla
);
212 EXPECT_EQ(vanilla
& vanilla
, vanilla
);
213 EXPECT_EQ(vanilla
& bespoke
, bottom
);
214 EXPECT_EQ(vanilla
& bottom
, bottom
);
215 EXPECT_EQ(vanilla
& foo
, bottom
);
216 EXPECT_EQ(bespoke
& top
, bespoke
);
217 EXPECT_EQ(bespoke
& vanilla
, bottom
);
218 EXPECT_EQ(bespoke
& bespoke
, bespoke
);
219 EXPECT_EQ(bespoke
& bottom
, bottom
);
220 EXPECT_EQ(bespoke
& foo
, foo
);
221 EXPECT_EQ(bottom
& top
, bottom
);
222 EXPECT_EQ(bottom
& vanilla
, bottom
);
223 EXPECT_EQ(bottom
& bespoke
, bottom
);
224 EXPECT_EQ(bottom
& bottom
, bottom
);
225 EXPECT_EQ(bottom
& foo
, bottom
);
226 EXPECT_EQ(foo
& top
, foo
);
227 EXPECT_EQ(foo
& vanilla
, bottom
);
228 EXPECT_EQ(foo
& bespoke
, foo
);
229 EXPECT_EQ(foo
& bottom
, bottom
);
230 EXPECT_EQ(foo
& foo
, foo
);
233 TEST(Type
, ToString
) {
234 EXPECT_EQ("Int", TInt
.toString());
235 EXPECT_EQ("Cell", TCell
.toString());
237 EXPECT_EQ("Vec", TVec
.toString());
238 EXPECT_EQ("Dict", TDict
.toString());
239 EXPECT_EQ("Keyset", TKeyset
.toString());
241 EXPECT_EQ("LazyCls", TLazyCls
.toString());
243 auto const sub
= Type::SubObj(SystemLib::s_HH_IteratorClass
);
244 auto const exact
= Type::ExactObj(SystemLib::s_HH_IteratorClass
);
246 EXPECT_EQ("Obj<=HH\\Iterator", sub
.toString());
247 EXPECT_EQ("Obj=HH\\Iterator", exact
.toString());
248 EXPECT_EQ("PtrToStr", TPtrToStr
.toString());
249 EXPECT_EQ("LvalToStr", TLvalToStr
.toString());
251 EXPECT_EQ("PtrTo{Prop|MIS|MMisc|Other|Field}Cell",
252 (TPtrToMembCell
- TPtrToElemCell
).toString());
253 EXPECT_EQ("LvalTo{Prop|MIS|MMisc|Other|Field}Cell",
254 (TLvalToMembCell
- TLvalToElemCell
).toString());
255 EXPECT_EQ("PtrToMembCell", TPtrToMembCell
.toString());
256 EXPECT_EQ("LvalToMembCell", TLvalToMembCell
.toString());
257 EXPECT_EQ("MemToInt", TMemToInt
.toString());
258 EXPECT_EQ("PtrTo{Str|Int}|LvalTo{Str|Int}",
259 (TMemToInt
| TMemToStr
).toString());
261 EXPECT_EQ("PtrTo{Int|StaticStr}|{Int|StaticStr}",
262 (TInt
| TPtrToStaticStr
).toString());
263 EXPECT_EQ("LvalTo{Int|StaticStr}|{Int|StaticStr}",
264 (TInt
| TLvalToStaticStr
).toString());
265 EXPECT_EQ("{Obj<=HH\\Iterator|Int}", (TInt
| sub
).toString());
267 EXPECT_EQ("Cls<=HH\\Iterator",
268 Type::SubCls(SystemLib::s_HH_IteratorClass
).toString());
269 EXPECT_EQ("Cls=HH\\Iterator",
270 Type::ExactCls(SystemLib::s_HH_IteratorClass
).toString());
272 EXPECT_EQ("{ABC|Func}", (TABC
| TFunc
).toString());
274 EXPECT_EQ("InitNull", TInitNull
.constValString());
276 EXPECT_EQ("InitCell", TInitCell
.toString());
277 EXPECT_EQ("PtrToInitCell", TInitCell
.ptr(Ptr::Ptr
).toString());
278 EXPECT_EQ("PtrToFrameInitCell", TPtrToFrameInitCell
.toString());
279 EXPECT_EQ("LvalToFrameInitCell", TLvalToFrameInitCell
.toString());
281 auto const ptrCns
= Type::cns((TypedValue
*)0xba5eba11, TPtrToMembInitNull
);
282 EXPECT_EQ("PtrToMembInitNull<TV: 0xba5eba11>", ptrCns
.toString());
283 EXPECT_EQ("TV: 0xba5eba11", ptrCns
.constValString());
287 EXPECT_TRUE(TPtrToInt
<= TPtrToCell
);
289 EXPECT_EQ(TPtrToInt
, TInt
.ptr(Ptr::Ptr
));
290 EXPECT_EQ(TPtrToCell
, TCell
.ptr(Ptr::Ptr
));
291 EXPECT_EQ(TInt
, TPtrToInt
.deref());
293 EXPECT_EQ(TPtrToInt
, TPtrToInt
- TInt
);
294 EXPECT_EQ(TInt
, (TPtrToInt
| TInt
) - TPtrToInt
);
295 EXPECT_EQ(TPtrToUncountedInit
, TPtrToUncounted
- TPtrToUninit
);
297 auto const t
= TPtrToInt
| TPtrToStr
| TInt
| TStr
;
298 EXPECT_EQ(t
, t
- TPtrToInt
);
299 EXPECT_EQ(t
, t
- TInt
);
300 EXPECT_EQ(TPtrToInt
| TPtrToStr
, t
- (TInt
| TStr
));
301 EXPECT_EQ(TInt
| TStr
, t
- (TPtrToInt
| TPtrToStr
));
303 EXPECT_EQ(TBottom
, TPtrToInt
& TInt
);
304 auto const a1
= TVec
.ptr(Ptr::Frame
);
305 auto const a2
= TDict
.ptr(Ptr::Frame
);
306 EXPECT_EQ(TBottom
, a1
& a2
);
307 EXPECT_EQ(a1
, a1
- a2
);
309 EXPECT_EQ(TPtrToLazyCls
, TLazyCls
.ptr(Ptr::Ptr
));
310 EXPECT_EQ(TLazyCls
, TPtrToLazyCls
.deref());
311 EXPECT_EQ(TBottom
, TPtrToLazyCls
& TLazyCls
);
313 EXPECT_EQ(TBottom
, TBottom
.deref());
315 auto const vanillaSpec
= ArraySpec(ArrayLayout::Vanilla());
316 auto const vecData
= ArrayData::GetScalarArray(make_vec_array(1, 2, 3, 4));
317 auto const ptrToConstVec
= Type::cns(vecData
).ptr(Ptr::Ptr
);
318 EXPECT_TRUE(ptrToConstVec
< TPtrToStaticVec
);
319 EXPECT_FALSE(ptrToConstVec
.hasConstVal());
320 EXPECT_TRUE(ptrToConstVec
.isSpecialized());
321 EXPECT_EQ(TPtrToStaticVec
, ptrToConstVec
.unspecialize());
322 EXPECT_EQ(vanillaSpec
, ptrToConstVec
.arrSpec());
324 auto const ptrToStaticVanillaVec
= TStaticVec
.narrowToVanilla().ptr(Ptr::Ptr
);
325 EXPECT_TRUE(ptrToStaticVanillaVec
< TPtrToStaticVec
);
326 EXPECT_FALSE(ptrToStaticVanillaVec
.hasConstVal());
327 EXPECT_TRUE(ptrToStaticVanillaVec
.isSpecialized());
328 EXPECT_EQ(TPtrToStaticVec
, ptrToStaticVanillaVec
.unspecialize());
329 EXPECT_EQ(vanillaSpec
, ptrToStaticVanillaVec
.arrSpec());
331 auto const ptrToStaticVec
= TStaticVec
.ptr(Ptr::Ptr
);
332 EXPECT_EQ(TPtrToStaticVec
, ptrToStaticVec
);
333 EXPECT_FALSE(ptrToStaticVec
.hasConstVal());
334 EXPECT_FALSE(ptrToStaticVec
.isSpecialized());
335 EXPECT_EQ(TPtrToStaticVec
, ptrToStaticVec
.unspecialize());
336 EXPECT_EQ(ArraySpec::Top(), ptrToStaticVec
.arrSpec());
338 auto const ptrToVanillaVec
= TVanillaVec
.ptr(Ptr::Ptr
);
339 EXPECT_TRUE(ptrToVanillaVec
< TPtrToVec
);
340 EXPECT_FALSE(ptrToVanillaVec
.hasConstVal());
341 EXPECT_TRUE(ptrToVanillaVec
.isSpecialized());
342 EXPECT_EQ(TPtrToVec
, ptrToVanillaVec
.unspecialize());
343 EXPECT_EQ(vanillaSpec
, ptrToVanillaVec
.arrSpec());
345 auto const ptrToVec
= TVec
.ptr(Ptr::Ptr
);
346 EXPECT_EQ(TPtrToVec
, ptrToVec
);
347 EXPECT_FALSE(ptrToVec
.hasConstVal());
348 EXPECT_FALSE(ptrToVec
.isSpecialized());
349 EXPECT_EQ(TPtrToVec
, ptrToVec
.unspecialize());
350 EXPECT_EQ(ArraySpec::Top(), ptrToVec
.arrSpec());
353 Type::ExactObj(SystemLib::s_HH_IteratorClass
).ptr(Ptr::Ptr
);
354 auto exactClassSpec
=
355 ClassSpec(SystemLib::s_HH_IteratorClass
, ClassSpec::ExactTag
{});
356 EXPECT_FALSE(ptrToExactObj
.hasConstVal());
357 EXPECT_TRUE(ptrToExactObj
.isSpecialized());
358 EXPECT_EQ(TPtrToObj
, ptrToExactObj
.unspecialize());
359 EXPECT_EQ(exactClassSpec
, ptrToExactObj
.clsSpec());
361 auto ptrToSubObj
= Type::SubObj(SystemLib::s_HH_IteratorClass
).ptr(Ptr::Ptr
);
363 ClassSpec(SystemLib::s_HH_IteratorClass
, ClassSpec::SubTag
{});
364 EXPECT_FALSE(ptrToSubObj
.hasConstVal());
365 EXPECT_TRUE(ptrToSubObj
.isSpecialized());
366 EXPECT_EQ(TPtrToObj
, ptrToSubObj
.unspecialize());
367 EXPECT_EQ(subClassSpec
, ptrToSubObj
.clsSpec());
371 EXPECT_TRUE(TLvalToInt
<= TLvalToCell
);
373 EXPECT_EQ(TInt
, TLvalToInt
.deref());
375 EXPECT_EQ(TLvalToInt
, TLvalToInt
- TInt
);
376 EXPECT_EQ(TInt
, (TLvalToInt
| TInt
) - TLvalToInt
);
377 EXPECT_EQ(TLvalToUncountedInit
, TLvalToUncounted
- TLvalToUninit
);
379 auto const t
= TLvalToInt
| TLvalToStr
| TInt
| TStr
;
380 EXPECT_EQ(t
, t
- TLvalToInt
);
381 EXPECT_EQ(t
, t
- TInt
);
382 EXPECT_EQ(TLvalToInt
| TLvalToStr
, t
- (TInt
| TStr
));
383 EXPECT_EQ(TInt
| TStr
, t
- (TLvalToInt
| TLvalToStr
));
385 EXPECT_EQ(TBottom
, TLvalToInt
& TInt
);
389 EXPECT_TRUE(TMemToInt
<= TMemToCell
);
391 EXPECT_EQ(TInt
, TMemToInt
.deref());
393 EXPECT_EQ(TMemToInt
, TMemToInt
- TInt
);
394 EXPECT_EQ(TInt
, (TMemToInt
| TInt
) - TMemToInt
);
395 EXPECT_EQ(TMemToUncountedInit
, TMemToUncounted
- TMemToUninit
);
397 auto const t
= TMemToInt
| TMemToStr
| TInt
| TStr
;
398 EXPECT_EQ(t
, t
- TMemToInt
);
399 EXPECT_EQ(t
, t
- TInt
);
400 EXPECT_EQ(TMemToInt
| TMemToStr
, t
- (TInt
| TStr
));
401 EXPECT_EQ(TInt
| TStr
, t
- (TMemToInt
| TMemToStr
));
403 EXPECT_EQ(TBottom
, TMemToInt
& TInt
);
406 TEST(Type
, MemPtrLval
) {
407 EXPECT_TRUE(TPtrToInt
<= TMemToCell
);
408 EXPECT_TRUE(TLvalToInt
<= TMemToCell
);
409 EXPECT_FALSE(TInt
<= TMemToCell
);
411 EXPECT_EQ(TBottom
, TPtrToInt
& TLvalToInt
);
412 EXPECT_EQ(TBottom
, TPtrToCell
& TLvalToCell
);
413 EXPECT_EQ(TPtrToInt
, TPtrToInt
& TMemToCell
);
415 EXPECT_EQ(TPtrToInt
, TMemToInt
- TLvalToInt
);
416 EXPECT_EQ(TLvalToInt
, TMemToInt
- TPtrToInt
);
418 auto const t
= TInt
| TPtrToInt
| TLvalToInt
;
419 EXPECT_EQ(TInt
, t
- (TPtrToInt
| TLvalToInt
));
420 EXPECT_EQ(TPtrToInt
, t
- (TInt
| TLvalToInt
));
421 EXPECT_EQ(TLvalToInt
, t
- (TInt
| TPtrToInt
));
422 EXPECT_EQ(TPtrToInt
| TLvalToInt
, t
- TInt
);
423 EXPECT_EQ(TInt
| TLvalToInt
, t
- TPtrToInt
);
424 EXPECT_EQ(TInt
| TPtrToInt
, t
- TLvalToInt
);
426 EXPECT_EQ(t
| TStr
| TMemToStr
, t
| TStr
);
427 EXPECT_EQ(t
| TStr
| TMemToStr
, (t
| TStr
) - TLvalToInt
);
429 EXPECT_EQ(TLvalToUncounted
, TLvalToUncounted
- TPtrToUninit
);
432 TEST(Type
, Subtypes
) {
433 Type numbers
= TDbl
| TInt
;
434 EXPECT_EQ("{Dbl|Int}", numbers
.toString());
435 EXPECT_TRUE(TDbl
<= numbers
);
436 EXPECT_TRUE(TInt
<= numbers
);
437 EXPECT_FALSE(TBool
<= numbers
);
439 EXPECT_TRUE(TFunc
<= TCell
);
440 EXPECT_FALSE(TTCA
<= TCell
);
442 EXPECT_TRUE(TVec
<= TArrLike
);
443 EXPECT_TRUE(TDict
<= TArrLike
);
444 EXPECT_TRUE(TKeyset
<= TArrLike
);
446 Type funcOrlcls
= TFunc
| TLazyCls
;
447 EXPECT_EQ("{Func|LazyCls}", funcOrlcls
.toString());
448 EXPECT_TRUE(TLazyCls
<= funcOrlcls
);
449 EXPECT_FALSE(TCls
<= funcOrlcls
);
453 for (auto t
: allTypes()) {
454 EXPECT_TRUE(t
<= TTop
);
456 for (auto t
: allTypes()) {
457 if (t
== TTop
) continue;
458 EXPECT_FALSE(TTop
<= t
);
463 inline bool fits(Type t
, GuardConstraint gc
) {
464 return typeFitsConstraint(t
, gc
);
468 TEST(Type
, GuardConstraints
) {
469 EXPECT_TRUE(fits(TCell
, DataTypeGeneric
));
470 EXPECT_FALSE(fits(TCell
, DataTypeCountnessInit
));
471 EXPECT_FALSE(fits(TCell
, DataTypeSpecific
));
473 EXPECT_TRUE(fits(TCell
, {DataTypeGeneric
}));
475 auto const vanillaConstraint
=
476 GuardConstraint(DataTypeSpecialized
).setArrayLayoutSensitive();
477 EXPECT_FALSE(fits(TCell
, vanillaConstraint
));
478 EXPECT_FALSE(fits(TArrLike
, vanillaConstraint
));
479 EXPECT_FALSE(fits(TVec
, vanillaConstraint
));
480 EXPECT_FALSE(fits(TVanillaArrLike
, vanillaConstraint
));
481 EXPECT_TRUE(fits(TVanillaVec
, vanillaConstraint
));
484 TEST(Type
, RelaxType
) {
485 auto gc
= GuardConstraint
{DataTypeSpecialized
};
486 gc
.setDesiredClass(SystemLib::s_HH_IteratorClass
);
487 gc
.category
= DataTypeSpecialized
;
488 auto subIter
= Type::SubObj(SystemLib::s_HH_IteratorClass
);
489 EXPECT_EQ("Obj<=HH\\Iterator", subIter
.toString());
490 EXPECT_EQ(subIter
, relaxType(subIter
, gc
.category
));
493 TEST(Type
, RelaxConstraint
) {
494 EXPECT_EQ(GuardConstraint(DataTypeCountnessInit
),
495 relaxConstraint(GuardConstraint
{DataTypeSpecific
}, TCell
, TDict
));
498 TEST(Type
, Specialized
) {
499 EXPECT_LE(TVanillaArrLike
, TArrLike
);
500 EXPECT_LT(TVanillaArrLike
, TArrLike
);
501 EXPECT_FALSE(TArrLike
<= TVanillaArrLike
);
502 EXPECT_LT(TVanillaArrLike
, TArrLike
| TObj
);
503 EXPECT_EQ(TVanillaArrLike
, TVanillaArrLike
& (TArrLike
| TCounted
));
504 EXPECT_GE(TVanillaArrLike
, TBottom
);
505 EXPECT_GT(TVanillaArrLike
, TBottom
);
507 EXPECT_TRUE(TInt
<= (TVanillaArrLike
| TInt
));
509 EXPECT_EQ(TBottom
, TVanillaArrLike
& TObj
);
510 EXPECT_EQ(TBottom
, TVanillaArrLike
- TArrLike
);
512 auto const vecData
= ArrayData::GetScalarArray(make_vec_array(1, 2, 3, 4));
513 auto const dictData
= ArrayData::GetScalarArray(make_dict_array(1, 1, 2, 2));
514 auto const constVec
= Type::cns(vecData
);
515 auto const constDict
= Type::cns(dictData
);
517 // Basic checks on constant array types.
519 EXPECT_TRUE(constDict
.hasConstVal());
520 EXPECT_TRUE(constDict
<= TArrLike
);
521 EXPECT_TRUE(constDict
<= TDict
);
522 EXPECT_TRUE(constDict
< TDict
);
523 EXPECT_TRUE(constDict
<= TStaticDict
);
524 EXPECT_TRUE(constDict
< TStaticDict
);
525 EXPECT_FALSE(constDict
<= TVec
);
527 EXPECT_TRUE(constVec
.hasConstVal());
528 EXPECT_TRUE(constVec
<= TArrLike
);
529 EXPECT_TRUE(constVec
<= TVec
);
530 EXPECT_TRUE(constVec
< TVec
);
531 EXPECT_TRUE(constVec
<= TStaticVec
);
532 EXPECT_TRUE(constVec
< TStaticVec
);
533 EXPECT_FALSE(constVec
<= TDict
);
535 // For some difference types, we are pessimistic: we had better not narrow
536 // these differences to TBottom, but we can't represent them finely.
537 EXPECT_EQ(TStaticVec
, TStaticVec
- constVec
);
538 EXPECT_EQ(TBottom
, constVec
- TStaticVec
);
539 EXPECT_EQ(constDict
, constDict
- TStaticVec
);
540 EXPECT_EQ(TBottom
, constDict
- TDict
);
542 // Checking specialization dropping. We cannot specialize on two dimensions
543 // (e.g. array-like and object) at the same time.
544 EXPECT_EQ(TStaticVec
| TObj
, constVec
| TObj
);
545 auto const subIter
= Type::SubObj(SystemLib::s_HH_IteratorClass
);
546 EXPECT_EQ(TVec
| TObj
, TVec
| subIter
);
548 auto const vecOrInt
= TVec
| TInt
;
549 EXPECT_EQ(TInt
, vecOrInt
- TArrLike
);
550 EXPECT_EQ(TInt
, vecOrInt
- TVec
);
551 EXPECT_EQ(TVec
, vecOrInt
- TInt
);
552 EXPECT_EQ(TPtrToVec
, TPtrToVec
- constVec
.ptr(Ptr::Ptr
));
554 auto const iterOrStr
= subIter
| TStr
;
555 EXPECT_EQ(TStr
, iterOrStr
- TObj
);
556 EXPECT_EQ(TStr
, iterOrStr
- subIter
);
557 EXPECT_EQ(subIter
, iterOrStr
- TStr
);
558 EXPECT_EQ(TPtrToObj
, TPtrToObj
- subIter
.ptr(Ptr::Ptr
));
560 auto const subCls
= Type::SubCls(SystemLib::s_HH_IteratorClass
);
561 EXPECT_EQ(TCls
, TCls
- subCls
);
563 auto const lclsOrStr
= TLazyCls
| TStr
;
564 EXPECT_EQ(TStr
, lclsOrStr
- TLazyCls
);
565 EXPECT_EQ(TLazyCls
, lclsOrStr
- TStr
);
568 TEST(Type
, ArrayFitsSpec
) {
569 auto const nonempty
= RepoAuthType::Array::Empty::No
;
570 auto const maybe_empty
= RepoAuthType::Array::Empty::Maybe
;
571 auto const str_rat
= RepoAuthType(RepoAuthType::Tag::Str
);
572 auto const int_rat
= RepoAuthType(RepoAuthType::Tag::Int
);
574 ArrayTypeTable::Builder builder
;
575 auto const rat1
= builder
.tuple(nonempty
, {int_rat
, int_rat
});
576 auto const rat2
= builder
.tuple(maybe_empty
, {int_rat
, str_rat
});
577 auto const rat3
= builder
.packed(nonempty
, int_rat
);
579 auto const ratType1
= Type::Vec(rat1
);
580 auto const ratType2
= Type::Vec(rat2
);
581 auto const ratType3
= Type::Vec(rat3
);
583 auto const vec1
= ArrayData::GetScalarArray(make_vec_array(2, 3));
584 auto const vec2
= ArrayData::GetScalarArray(make_vec_array(2, ""));
585 auto const vec3
= ArrayData::GetScalarArray(make_vec_array(2, 3, 5));
587 DictInit dict_init1
{2};
588 dict_init1
.set((int64_t)0, 2);
589 dict_init1
.set((int64_t)1, 3);
590 auto const dict1
= ArrayData::GetScalarArray(dict_init1
.toArray());
592 DictInit dict_init2
{2};
593 dict_init2
.set(17, 2);
594 dict_init2
.set(19, 3);
595 auto const dict2
= ArrayData::GetScalarArray(dict_init2
.toArray());
597 EXPECT_FALSE(Type::cns(staticEmptyVec()) <= ratType1
);
598 EXPECT_TRUE(Type::cns(staticEmptyVec()) <= ratType2
);
599 EXPECT_FALSE(Type::cns(staticEmptyVec()) <= ratType3
);
601 EXPECT_TRUE(Type::cns(vec1
) <= ratType1
);
602 EXPECT_FALSE(Type::cns(vec1
) <= ratType2
);
603 EXPECT_TRUE(Type::cns(vec1
) <= ratType3
);
605 EXPECT_FALSE(Type::cns(vec2
) <= ratType1
);
606 EXPECT_TRUE(Type::cns(vec2
) <= ratType2
);
607 EXPECT_FALSE(Type::cns(vec2
) <= ratType3
);
609 EXPECT_FALSE(Type::cns(vec3
) <= ratType1
);
610 EXPECT_FALSE(Type::cns(vec3
) <= ratType2
);
611 EXPECT_TRUE(Type::cns(vec3
) <= ratType3
);
613 EXPECT_FALSE(Type::cns(dict1
) <= ratType1
);
614 EXPECT_FALSE(Type::cns(dict1
) <= ratType2
);
615 EXPECT_FALSE(Type::cns(dict1
) <= ratType3
);
617 EXPECT_FALSE(Type::cns(dict2
) <= ratType1
);
618 EXPECT_FALSE(Type::cns(dict2
) <= ratType2
);
619 EXPECT_FALSE(Type::cns(dict2
) <= ratType3
);
621 EXPECT_LE(TUninit
, ratType1
| TNull
);
622 EXPECT_FALSE((ratType1
| TNull
) <= TUninit
);
624 EXPECT_LE(TUninit
, ratType3
| TNull
);
625 EXPECT_FALSE((ratType3
| TNull
) <= TUninit
);
628 TEST(Type
, SpecializedArrays
) {
629 EXPECT_FALSE(TArrLike
.isSpecialized());
630 EXPECT_FALSE(TArrLike
.arrSpec());
631 EXPECT_FALSE(TArrLike
.arrSpec().vanilla());
633 auto const const_array
= Type::cns(staticEmptyVec());
634 EXPECT_TRUE(const_array
.isSpecialized());
635 EXPECT_TRUE(const_array
.arrSpec());
636 EXPECT_TRUE(const_array
.arrSpec().vanilla());
638 EXPECT_FALSE(TDict
.isSpecialized());
639 EXPECT_FALSE(TDict
.arrSpec());
640 EXPECT_FALSE(TDict
.arrSpec().vanilla());
642 auto const const_dict
= Type::cns(staticEmptyDictArray());
643 EXPECT_TRUE(const_dict
.isSpecialized());
644 EXPECT_TRUE(const_dict
.arrSpec());
645 EXPECT_TRUE(const_dict
.arrSpec().vanilla());
648 TEST(Type
, SpecializedObjects
) {
649 auto const A
= SystemLib::s_HH_IteratorClass
;
650 auto const B
= SystemLib::s_HH_TraversableClass
;
651 EXPECT_TRUE(A
->classof(B
));
653 auto const obj
= TObj
;
654 auto const exactA
= Type::ExactObj(A
);
655 auto const exactB
= Type::ExactObj(B
);
656 auto const subA
= Type::SubObj(A
);
657 auto const subB
= Type::SubObj(B
);
659 EXPECT_EQ(exactA
.clsSpec().cls(), A
);
660 EXPECT_EQ(subA
.clsSpec().cls(), A
);
662 EXPECT_EQ(exactA
.clsSpec().exactCls(), A
);
663 EXPECT_EQ(subA
.clsSpec().exactCls(), nullptr);
665 EXPECT_LE(exactA
, exactA
);
666 EXPECT_LE(subA
, subA
);
668 EXPECT_LT(exactA
, obj
);
669 EXPECT_LT(subA
, obj
);
671 EXPECT_LE(TBottom
, subA
);
672 EXPECT_LE(TBottom
, exactA
);
674 EXPECT_LT(exactA
, subA
);
676 EXPECT_LT(exactA
, subB
);
677 EXPECT_LT(subA
, subB
);
679 EXPECT_FALSE(exactA
<= exactB
);
680 EXPECT_FALSE(subA
<= exactB
);
682 EXPECT_EQ(exactA
& subA
, exactA
);
683 EXPECT_EQ(subA
& exactA
, exactA
);
684 EXPECT_EQ(exactB
& subB
, exactB
);
685 EXPECT_EQ(subB
& exactB
, exactB
);
687 EXPECT_EQ(TObj
, TObj
- subA
); // conservative
688 EXPECT_EQ(subA
, subA
- exactA
); // conservative
691 TEST(Type
, SpecializedClass
) {
692 auto const A
= SystemLib::s_HH_IteratorClass
;
693 auto const B
= SystemLib::s_HH_TraversableClass
;
695 EXPECT_TRUE(A
->classof(B
));
697 auto const cls
= TCls
;
698 auto const exactA
= Type::ExactCls(A
);
699 auto const exactB
= Type::ExactCls(B
);
700 auto const subA
= Type::SubCls(A
);
701 auto const subB
= Type::SubCls(B
);
703 EXPECT_EQ(exactA
.clsSpec().exactCls(), A
);
704 EXPECT_EQ(subA
.clsSpec().cls(), A
);
705 EXPECT_EQ(subA
.clsSpec().exactCls(), nullptr);
707 EXPECT_LE(exactA
, exactA
);
708 EXPECT_LE(subA
, subA
);
710 EXPECT_LT(exactA
, cls
);
711 EXPECT_LT(subA
, cls
);
713 EXPECT_LE(TBottom
, exactA
);
714 EXPECT_LE(TBottom
, subA
);
716 EXPECT_LT(exactA
, subA
);
718 EXPECT_LT(exactA
, subB
);
719 EXPECT_LT(subA
, subB
);
721 EXPECT_FALSE(exactA
<= exactB
);
722 EXPECT_FALSE(subA
<= exactB
);
724 EXPECT_EQ(exactA
& subA
, exactA
);
725 EXPECT_EQ(subA
& exactA
, exactA
);
726 EXPECT_EQ(exactB
& subB
, exactB
);
727 EXPECT_EQ(subB
& exactB
, exactB
);
729 EXPECT_EQ(cls
, cls
- subA
); // conservative
730 EXPECT_EQ(subA
, subA
- exactA
); // conservative
732 EXPECT_LE(TUninit
, exactA
| TNull
);
733 EXPECT_FALSE((exactA
| TNull
) <= TUninit
);
735 EXPECT_LE(TUninit
, subA
| TNull
);
736 EXPECT_FALSE((subA
| TNull
) <= TUninit
);
740 auto five
= Type::cns(5);
741 auto fiveArr
= five
| TArrLike
;
742 EXPECT_LT(five
, TInt
);
743 EXPECT_NE(five
, TInt
);
744 EXPECT_TRUE(five
.hasConstVal());
745 EXPECT_EQ(5, five
.intVal());
746 EXPECT_TRUE(five
.hasConstVal(TInt
));
747 EXPECT_TRUE(five
.hasConstVal(5));
748 EXPECT_FALSE(five
.hasConstVal(5.0));
749 EXPECT_TRUE(TCell
.maybe(five
));
750 EXPECT_EQ(TInt
, five
| TInt
);
751 EXPECT_EQ(TInt
, five
| Type::cns(10));
752 EXPECT_EQ(five
, five
| Type::cns(5));
753 EXPECT_EQ(five
, Type::cns(5) & five
);
754 EXPECT_EQ(five
, five
& TInt
);
755 EXPECT_EQ(five
, TCell
& five
);
756 EXPECT_EQ("Int<5>", five
.toString());
757 EXPECT_EQ(five
, five
- TArrLike
);
758 EXPECT_EQ(five
, five
- Type::cns(1));
759 EXPECT_EQ(TInt
, TInt
- five
); // conservative
760 EXPECT_EQ(TInt
, fiveArr
- TArrLike
);
761 EXPECT_EQ(fiveArr
, fiveArr
- five
);
762 EXPECT_EQ(TArrLike
, fiveArr
- TInt
);
763 EXPECT_EQ(TBottom
, five
- TInt
);
764 EXPECT_EQ(TBottom
, five
- five
);
765 EXPECT_EQ(TPtrToCell
,
766 (TPtrToCell
|TNullptr
) - TNullptr
);
767 EXPECT_EQ(TInt
, five
.dropConstVal());
768 EXPECT_TRUE(!five
.maybe(Type::cns(2)));
770 auto True
= Type::cns(true);
771 EXPECT_EQ("Bool<true>", True
.toString());
772 EXPECT_LT(True
, TBool
);
773 EXPECT_NE(True
, TBool
);
774 EXPECT_TRUE(True
.hasConstVal());
775 EXPECT_TRUE(True
.boolVal());
776 EXPECT_TRUE(TUncounted
.maybe(True
));
777 EXPECT_FALSE(five
<= True
);
778 EXPECT_FALSE(five
> True
);
780 EXPECT_TRUE(!five
.maybe(True
));
781 EXPECT_EQ(TInt
| TBool
, five
| True
);
782 EXPECT_EQ(TBottom
, five
& True
);
783 EXPECT_EQ(Type::cns(false), TBool
- True
);
785 auto const arrData
= ArrayData::GetScalarArray(make_dict_array(1, 2, 3, 4));
786 auto const constArray
= Type::cns(arrData
);
788 EXPECT_EQ(constArray
, constArray
& TDict
);
789 EXPECT_TRUE(constArray
<= constArray
);
790 EXPECT_TRUE(constArray
<= TDict
);
791 EXPECT_TRUE(constArray
< TDict
);
792 EXPECT_FALSE(TDict
<= constArray
);
793 EXPECT_FALSE(TDict
<= TVec
);
795 ArrayTypeTable::Builder ratBuilder
;
796 auto const rat1
= ratBuilder
.packed(RepoAuthType::Array::Empty::No
,
797 RepoAuthType(RepoAuthType::Tag::Str
));
798 auto const ratArray1
= Type::Dict(rat1
);
799 auto const rat2
= ratBuilder
.packed(RepoAuthType::Array::Empty::No
,
800 RepoAuthType(RepoAuthType::Tag::Int
));
801 auto const ratArray2
= Type::Dict(rat2
);
802 EXPECT_EQ(ratArray1
, ratArray1
& ratArray2
);
803 EXPECT_EQ(ratArray1
, ratArray2
& ratArray1
);
804 EXPECT_TRUE(ratArray1
<= TArrLike
);
805 EXPECT_TRUE(ratArray1
< TArrLike
);
806 EXPECT_TRUE(ratArray1
<= TDict
);
807 EXPECT_TRUE(ratArray1
< TDict
);
808 EXPECT_TRUE(ratArray1
<= ratArray1
);
809 EXPECT_TRUE(ratArray1
< (TDict
|TObj
));
810 EXPECT_FALSE(ratArray1
< ratArray2
);
811 EXPECT_NE(ratArray1
, ratArray2
);
813 auto const vanillaRat
= ratArray1
& TVanillaArrLike
;
814 EXPECT_EQ("ArrLike=Vanilla", TVanillaArrLike
.toString());
815 EXPECT_EQ("Dict=Vanilla:N([Str])", vanillaRat
.toString());
816 EXPECT_TRUE(vanillaRat
<= TVanillaArrLike
);
817 EXPECT_TRUE(vanillaRat
< TVanillaArrLike
);
818 EXPECT_TRUE(vanillaRat
<= TVanillaDict
);
819 EXPECT_TRUE(vanillaRat
< TVanillaDict
);
820 EXPECT_TRUE(vanillaRat
<= ratArray1
);
821 EXPECT_TRUE(vanillaRat
< ratArray1
);
822 EXPECT_TRUE(vanillaRat
.arrSpec().vanilla());
824 auto const narrowedRat
= ratArray1
.narrowToVanilla();
825 EXPECT_EQ("Dict=N([Str])", ratArray1
.toString());
826 EXPECT_EQ("Dict=Vanilla:N([Str])", narrowedRat
.toString());
827 EXPECT_TRUE(narrowedRat
< ratArray1
);
828 EXPECT_TRUE(narrowedRat
<= ratArray1
);
829 EXPECT_FALSE(ratArray1
< narrowedRat
);
830 EXPECT_FALSE(ratArray1
<= narrowedRat
);
831 EXPECT_EQ(narrowedRat
, ratArray1
& TVanillaArrLike
);
832 EXPECT_FALSE(ratArray1
.arrSpec().vanilla());
834 auto const vec
= make_vec_array(1, 2, 3, 4);
835 auto const vecData
= ArrayData::GetScalarArray(std::move(vec
));
836 auto const constVec
= Type::cns(vecData
);
837 EXPECT_TRUE(constVec
< TVec
);
839 auto const dict
= make_dict_array(1, 1, 2, 2, 3, 3, 4, 4);
840 auto const dictData
= ArrayData::GetScalarArray(std::move(dict
));
841 auto const constDict
= Type::cns(dictData
);
842 EXPECT_TRUE(constDict
< TDict
);
844 auto const keyset
= make_keyset_array(1, 2, 3, 4);
845 auto const keysetData
= ArrayData::GetScalarArray(std::move(keyset
));
846 auto const constKeyset
= Type::cns(keysetData
);
847 EXPECT_TRUE(constKeyset
< TKeyset
);
849 auto constLazyCls
= Type::cns(LazyClassData::create(makeStaticString("Foo")));
850 EXPECT_TRUE(constLazyCls
< TLazyCls
);
851 EXPECT_TRUE(constLazyCls
.hasConstVal());
852 EXPECT_FALSE(TLazyCls
.hasConstVal());
853 EXPECT_EQ(TLazyCls
| TBool
, constLazyCls
| True
);
854 EXPECT_EQ(TBottom
, constLazyCls
& True
);
857 TEST(Type
, NarrowToVanilla
) {
858 EXPECT_EQ("Vec=Vanilla", TVec
.narrowToVanilla().toString());
859 EXPECT_EQ("{Dict|Vec}=Vanilla", (TVec
|TDict
).narrowToVanilla().toString());
860 EXPECT_EQ("{Vec=Vanilla|Int}", (TVec
|TInt
).narrowToVanilla().toString());
861 EXPECT_EQ("{Vec|Obj}", (TVec
|TObj
).narrowToVanilla().toString());
864 TEST(Type
, VanillaArray
) {
865 EXPECT_EQ("ArrLike=Vanilla", TVanillaArrLike
.toString());
866 EXPECT_TRUE(TVanillaArrLike
<= TArrLike
);
867 EXPECT_TRUE(TVanillaArrLike
< TArrLike
);
868 EXPECT_FALSE(TVanillaArrLike
.arrSpec().type());
869 EXPECT_TRUE(TVanillaArrLike
.arrSpec().vanilla());
872 TEST(Type
, VanillaVec
) {
873 EXPECT_EQ("Vec", TVec
.toString());
874 EXPECT_FALSE(TVec
.arrSpec().type());
875 EXPECT_FALSE(TVec
.arrSpec().vanilla());
877 EXPECT_EQ("Vec=Vanilla", TVanillaVec
.toString());
878 EXPECT_FALSE(TVanillaVec
.arrSpec().type());
879 EXPECT_TRUE(TVanillaVec
.arrSpec().vanilla());
880 EXPECT_EQ(TVanillaVec
, TVec
& TVanillaVec
);
881 EXPECT_EQ(TVanillaVec
, TVec
.narrowToVanilla());
883 EXPECT_FALSE(TVec
<= TVanillaVec
);
884 EXPECT_TRUE(TVanillaVec
<= TVec
);
885 EXPECT_FALSE(TVec
< TVanillaVec
);
886 EXPECT_TRUE(TVanillaVec
< TVec
);
889 TEST(Type
, BespokeVec
) {
890 auto const foo_layout
= ArrayLayout
{
891 bespoke::testing::makeDummyLayout("foo", {ArrayLayout::Bespoke()})
893 auto const bar_layout
= ArrayLayout
{
894 bespoke::testing::makeDummyLayout("bar", {ArrayLayout::Bespoke()})
897 auto const vecFoo
= TVec
.narrowToLayout(foo_layout
);
898 EXPECT_EQ("Vec=foo", vecFoo
.toString());
899 EXPECT_FALSE(TVec
<= vecFoo
);
900 EXPECT_FALSE(TVanillaVec
<= vecFoo
);
901 EXPECT_FALSE(vecFoo
<= TVanillaVec
);
902 EXPECT_EQ(vecFoo
| TVanillaVec
, TVec
);
903 EXPECT_EQ(TVanillaVec
& vecFoo
, TBottom
);
904 EXPECT_EQ(vecFoo
| TVec
, TVec
);
905 EXPECT_EQ(vecFoo
& TVec
, vecFoo
);
907 auto const vecBar
= TVec
.narrowToLayout(bar_layout
);
908 EXPECT_EQ("Vec=bar", vecBar
.toString());
910 auto const vecVanillaBar
= TVanillaVec
.narrowToLayout(bar_layout
);
911 EXPECT_EQ(TBottom
, vecVanillaBar
);
914 TEST(Type
, BespokeVecRAT
) {
915 RO::EvalBespokeArrayLikeMode
= 2;
916 auto const foo_layout
= ArrayLayout
{
917 bespoke::testing::makeDummyLayout("foo", {ArrayLayout::Bespoke()})
919 auto const bar_layout
= ArrayLayout
{
920 bespoke::testing::makeDummyLayout("bar", {ArrayLayout::Bespoke()})
922 bespoke::selectBespokeLayouts();
924 ArrayTypeTable::Builder ratBuilder
;
925 auto const rat
= ratBuilder
.packed(RepoAuthType::Array::Empty::No
,
926 RepoAuthType(RepoAuthType::Tag::Str
));
927 auto const vecRat
= Type::Vec(rat
);
928 EXPECT_EQ("Vec=N([Str])", vecRat
.toString());
929 auto const vecRatBespoke
= vecRat
.narrowToLayout(foo_layout
);
930 EXPECT_EQ("Vec=foo:N([Str])", vecRatBespoke
.toString());
931 auto const vecRatVanilla
= vecRat
.narrowToVanilla();
932 EXPECT_EQ("Vec=Vanilla:N([Str])", vecRatVanilla
.toString());
934 EXPECT_EQ(TBottom
, vecRatBespoke
.narrowToVanilla());
935 EXPECT_EQ(TBottom
, vecRatVanilla
.narrowToLayout(foo_layout
));
936 EXPECT_EQ(TBottom
, vecRatBespoke
.narrowToLayout(bar_layout
));
939 TEST(Type
, VanillaVecRAT
) {
940 ArrayTypeTable::Builder ratBuilder
;
941 auto const rat
= ratBuilder
.packed(RepoAuthType::Array::Empty::No
,
942 RepoAuthType(RepoAuthType::Tag::Str
));
943 auto const vecRat
= Type::Vec(rat
);
944 EXPECT_EQ("Vec=N([Str])", vecRat
.toString());
945 EXPECT_TRUE(vecRat
.arrSpec().type());
946 EXPECT_FALSE(vecRat
.arrSpec().vanilla());
948 auto const vanillaVecRat
= vecRat
.narrowToVanilla();
949 EXPECT_EQ("Vec=Vanilla:N([Str])", vanillaVecRat
.toString());
950 EXPECT_TRUE(vanillaVecRat
.arrSpec().type());
951 EXPECT_TRUE(vanillaVecRat
.arrSpec().vanilla());
952 EXPECT_EQ(vanillaVecRat
, vecRat
& TVanillaVec
);
954 EXPECT_FALSE(TVec
<= vecRat
);
955 EXPECT_TRUE(vecRat
<= TVec
);
956 EXPECT_FALSE(TVec
< vecRat
);
957 EXPECT_TRUE(vecRat
< TVec
);
959 EXPECT_TRUE(vanillaVecRat
<= TVec
);
960 EXPECT_TRUE(vanillaVecRat
< TVec
);
961 EXPECT_TRUE(vanillaVecRat
<= vecRat
);
962 EXPECT_FALSE(vecRat
< vanillaVecRat
);
963 EXPECT_TRUE(vanillaVecRat
<= TVanillaVec
);
964 EXPECT_TRUE(vanillaVecRat
< TVanillaVec
);
966 EXPECT_TRUE(vanillaVecRat
<= TVanillaVec
);
967 EXPECT_FALSE(vecRat
<= TVanillaVec
);
968 EXPECT_TRUE(vanillaVecRat
< TVanillaVec
);
969 EXPECT_FALSE(vecRat
< TVanillaVec
);
972 TEST(Type
, BespokeHierarchy
) {
980 RO::EvalBespokeArrayLikeMode
= 2;
981 bespoke::Layout::ClearHierarchy();
982 auto const foo_layout
= ArrayLayout
{
983 bespoke::testing::makeDummyAbstractLayout("foo", {ArrayLayout::Bespoke()})
985 auto const baz_layout
= ArrayLayout
{
986 bespoke::testing::makeDummyAbstractLayout("baz", {ArrayLayout::Bespoke()})
988 auto const bar_layout
= ArrayLayout
{
989 bespoke::testing::makeDummyLayout("bar", {foo_layout
})
991 auto const bat_layout
= ArrayLayout
{
992 bespoke::testing::makeDummyLayout("bat", {foo_layout
, baz_layout
})
994 auto const ter_layout
= ArrayLayout
{
995 bespoke::testing::makeDummyLayout("ter", {baz_layout
})
997 bespoke::selectBespokeLayouts();
999 auto const top
= TVec
.narrowToLayout(ArrayLayout::Bespoke());
1000 auto const foo
= TVec
.narrowToLayout(foo_layout
);
1001 auto const baz
= TVec
.narrowToLayout(baz_layout
);
1002 auto const bar
= TVec
.narrowToLayout(bar_layout
);
1003 auto const bat
= TVec
.narrowToLayout(bat_layout
);
1004 auto const ter
= TVec
.narrowToLayout(ter_layout
);
1005 auto const bot
= TBottom
;
1008 EXPECT_TRUE(top
<= top
);
1009 EXPECT_TRUE(foo
<= top
);
1010 EXPECT_TRUE(baz
<= top
);
1011 EXPECT_TRUE(bar
<= top
);
1012 EXPECT_TRUE(bat
<= top
);
1013 EXPECT_TRUE(ter
<= top
);
1015 EXPECT_FALSE(top
<= foo
);
1016 EXPECT_TRUE(foo
<= foo
);
1017 EXPECT_FALSE(baz
<= foo
);
1018 EXPECT_TRUE(bar
<= foo
);
1019 EXPECT_TRUE(bat
<= foo
);
1020 EXPECT_FALSE(ter
<= foo
);
1022 EXPECT_FALSE(top
<= bar
);
1023 EXPECT_FALSE(foo
<= bar
);
1024 EXPECT_FALSE(baz
<= bar
);
1025 EXPECT_TRUE(bar
<= bar
);
1026 EXPECT_FALSE(bat
<= bar
);
1027 EXPECT_FALSE(ter
<= bar
);
1029 EXPECT_FALSE(top
<= bat
);
1030 EXPECT_FALSE(foo
<= bat
);
1031 EXPECT_FALSE(baz
<= bat
);
1032 EXPECT_FALSE(bar
<= bat
);
1033 EXPECT_TRUE(bat
<= bat
);
1034 EXPECT_FALSE(ter
<= bat
);
1036 EXPECT_FALSE(top
<= baz
);
1037 EXPECT_FALSE(foo
<= baz
);
1038 EXPECT_TRUE(baz
<= baz
);
1039 EXPECT_FALSE(bar
<= baz
);
1040 EXPECT_TRUE(bat
<= baz
);
1041 EXPECT_TRUE(ter
<= baz
);
1043 EXPECT_FALSE(top
<= ter
);
1044 EXPECT_FALSE(foo
<= ter
);
1045 EXPECT_FALSE(baz
<= ter
);
1046 EXPECT_FALSE(bar
<= ter
);
1047 EXPECT_FALSE(bat
<= ter
);
1048 EXPECT_TRUE(ter
<= ter
);
1050 EXPECT_TRUE(bot
<= top
);
1051 EXPECT_TRUE(bot
<= foo
);
1052 EXPECT_TRUE(bot
<= baz
);
1053 EXPECT_TRUE(bot
<= bar
);
1054 EXPECT_TRUE(bot
<= bat
);
1055 EXPECT_TRUE(bot
<= ter
);
1058 EXPECT_EQ(top
, top
| top
);
1059 EXPECT_EQ(top
, top
| foo
);
1060 EXPECT_EQ(top
, top
| baz
);
1061 EXPECT_EQ(top
, top
| bar
);
1062 EXPECT_EQ(top
, top
| bat
);
1063 EXPECT_EQ(top
, top
| ter
);
1065 EXPECT_EQ(top
, foo
| top
);
1066 EXPECT_EQ(foo
, foo
| foo
);
1067 EXPECT_EQ(top
, foo
| baz
);
1068 EXPECT_EQ(foo
, foo
| bar
);
1069 EXPECT_EQ(foo
, foo
| bat
);
1070 EXPECT_EQ(top
, foo
| ter
);
1072 EXPECT_EQ(top
, baz
| top
);
1073 EXPECT_EQ(top
, baz
| foo
);
1074 EXPECT_EQ(baz
, baz
| baz
);
1075 EXPECT_EQ(top
, baz
| bar
);
1076 EXPECT_EQ(baz
, baz
| bat
);
1077 EXPECT_EQ(baz
, baz
| ter
);
1079 EXPECT_EQ(top
, bar
| top
);
1080 EXPECT_EQ(foo
, bar
| foo
);
1081 EXPECT_EQ(top
, bar
| baz
);
1082 EXPECT_EQ(bar
, bar
| bar
);
1083 EXPECT_EQ(foo
, bar
| bat
);
1084 EXPECT_EQ(top
, bar
| ter
);
1086 EXPECT_EQ(top
, bat
| top
);
1087 EXPECT_EQ(foo
, bat
| foo
);
1088 EXPECT_EQ(baz
, bat
| baz
);
1089 EXPECT_EQ(foo
, bat
| bar
);
1090 EXPECT_EQ(bat
, bat
| bat
);
1091 EXPECT_EQ(baz
, bat
| ter
);
1093 EXPECT_EQ(top
, ter
| top
);
1094 EXPECT_EQ(top
, ter
| foo
);
1095 EXPECT_EQ(baz
, ter
| baz
);
1096 EXPECT_EQ(top
, ter
| bar
);
1097 EXPECT_EQ(baz
, ter
| bat
);
1098 EXPECT_EQ(ter
, ter
| ter
);
1101 EXPECT_EQ(top
, top
& top
);
1102 EXPECT_EQ(foo
, top
& foo
);
1103 EXPECT_EQ(baz
, top
& baz
);
1104 EXPECT_EQ(bar
, top
& bar
);
1105 EXPECT_EQ(bat
, top
& bat
);
1106 EXPECT_EQ(ter
, top
& ter
);
1108 EXPECT_EQ(foo
, foo
& top
);
1109 EXPECT_EQ(foo
, foo
& foo
);
1110 EXPECT_EQ(bat
, foo
& baz
);
1111 EXPECT_EQ(bar
, foo
& bar
);
1112 EXPECT_EQ(bat
, foo
& bat
);
1113 EXPECT_EQ(bot
, foo
& ter
);
1115 EXPECT_EQ(baz
, baz
& top
);
1116 EXPECT_EQ(bat
, baz
& foo
);
1117 EXPECT_EQ(baz
, baz
& baz
);
1118 EXPECT_EQ(bot
, baz
& bar
);
1119 EXPECT_EQ(bat
, baz
& bat
);
1120 EXPECT_EQ(ter
, baz
& ter
);
1122 EXPECT_EQ(bar
, bar
& top
);
1123 EXPECT_EQ(bar
, bar
& foo
);
1124 EXPECT_EQ(bot
, bar
& baz
);
1125 EXPECT_EQ(bar
, bar
& bar
);
1126 EXPECT_EQ(bot
, bar
& bat
);
1127 EXPECT_EQ(bot
, bar
& ter
);
1129 EXPECT_EQ(bat
, bat
& top
);
1130 EXPECT_EQ(bat
, bat
& foo
);
1131 EXPECT_EQ(bat
, bat
& baz
);
1132 EXPECT_EQ(bot
, bat
& bar
);
1133 EXPECT_EQ(bat
, bat
& bat
);
1134 EXPECT_EQ(bot
, bat
& ter
);
1136 EXPECT_EQ(ter
, ter
& top
);
1137 EXPECT_EQ(bot
, ter
& foo
);
1138 EXPECT_EQ(ter
, ter
& baz
);
1139 EXPECT_EQ(bot
, ter
& bar
);
1140 EXPECT_EQ(bot
, ter
& bat
);
1141 EXPECT_EQ(ter
, ter
& ter
);
1144 TEST(Type
, BespokeRanges
) {
1154 RO::EvalBespokeArrayLikeMode
= 2;
1155 bespoke::Layout::ClearHierarchy();
1156 auto const foo_layout
= ArrayLayout
{
1157 bespoke::testing::makeDummyAbstractLayout("foo", {ArrayLayout::Bespoke()})
1159 auto const baz_layout
= ArrayLayout
{
1160 bespoke::testing::makeDummyAbstractLayout("baz", {ArrayLayout::Bespoke()})
1162 auto const bar_layout
= ArrayLayout
{
1163 bespoke::testing::makeDummyAbstractLayout("bar", {foo_layout
})
1165 auto const bat_layout
= ArrayLayout
{
1166 bespoke::testing::makeDummyLayout("bat", {foo_layout
, baz_layout
})
1168 auto const ter_layout
= ArrayLayout
{
1169 bespoke::testing::makeDummyLayout("ter", {baz_layout
})
1171 auto const qop_layout
= ArrayLayout
{
1172 bespoke::testing::makeDummyLayout("qup", {bar_layout
})
1174 bespoke::selectBespokeLayouts();
1176 foo_layout
.bespokeLayoutTest();
1177 baz_layout
.bespokeLayoutTest();
1178 bar_layout
.bespokeLayoutTest();
1179 bat_layout
.bespokeLayoutTest();
1180 ter_layout
.bespokeLayoutTest();
1181 qop_layout
.bespokeLayoutTest();
1184 TEST(Type
, PtrKinds
) {
1185 auto const frameCell
= TCell
.ptr(Ptr::Frame
);
1186 auto const frameUninit
= TUninit
.ptr(Ptr::Frame
);
1187 auto const frameBool
= TBool
.ptr(Ptr::Frame
);
1188 auto const unknownBool
= TBool
.ptr(Ptr::Ptr
);
1189 auto const unknownCell
= TCell
.ptr(Ptr::Ptr
);
1190 auto const stackObj
= TObj
.ptr(Ptr::Stk
);
1191 auto const stackBool
= TBool
.ptr(Ptr::Stk
);
1193 EXPECT_EQ("PtrToFrameCell", frameCell
.toString());
1194 EXPECT_EQ("PtrToFrameBool", frameBool
.toString());
1195 EXPECT_EQ("PtrToBool", unknownBool
.toString());
1196 EXPECT_EQ("PtrToStkObj", stackObj
.toString());
1197 EXPECT_EQ("Nullptr|PtrToPropCell",
1198 (TPtrToPropCell
|TNullptr
).toString());
1199 EXPECT_EQ("Nullptr|PtrToFieldCell",
1200 (TPtrToFieldCell
|TNullptr
).toString());
1202 EXPECT_EQ(Ptr::Frame
, (frameUninit
|frameBool
).ptrKind());
1204 EXPECT_TRUE(frameBool
<= unknownBool
);
1205 EXPECT_TRUE(frameBool
<= frameCell
);
1206 EXPECT_FALSE(frameBool
<= frameUninit
);
1207 EXPECT_TRUE(frameBool
.maybe(frameCell
));
1208 EXPECT_TRUE(frameBool
.maybe(unknownBool
));
1209 EXPECT_TRUE(!frameUninit
.maybe(frameBool
));
1210 EXPECT_TRUE(frameUninit
.maybe(frameCell
));
1211 EXPECT_TRUE(!frameUninit
.maybe(unknownBool
));
1212 EXPECT_TRUE(!TPtrToUninit
.maybe(TPtrToBool
));
1213 EXPECT_FALSE(unknownBool
<= frameBool
);
1214 EXPECT_EQ(unknownBool
, frameBool
| unknownBool
);
1216 EXPECT_EQ(unknownCell
, frameCell
| unknownBool
);
1218 EXPECT_EQ(TBottom
, frameBool
& stackBool
);
1219 EXPECT_EQ(frameBool
, frameBool
& unknownBool
);
1221 EXPECT_EQ(Ptr::Prop
,
1222 (TPtrToPropCell
|TNullptr
).ptrKind());
1223 EXPECT_EQ(TPtrToPropCell
,
1224 (TPtrToPropCell
|TNullptr
) - TNullptr
);
1225 EXPECT_EQ(Ptr::Field
,
1226 (TPtrToFieldCell
|TNullptr
).ptrKind());
1227 EXPECT_EQ(TPtrToFieldCell
,
1228 (TPtrToFieldCell
|TNullptr
) - TNullptr
);
1230 auto const frameCellOrCell
= frameCell
| TCell
;
1231 auto const stackOrArrOrInt
= TArrLike
.ptr(Ptr::Stk
) | TInt
;
1232 EXPECT_EQ(TInt
| TArrLike
, frameCellOrCell
& stackOrArrOrInt
);
1235 TEST(Type
, ConstantPtrTypes
) {
1236 std::vector
<TypedValue
> dicts
;
1237 for (auto const key
: {"foo", "bar"}) {
1239 dinit
.set(StringData::Make(key
), make_tv
<KindOfBoolean
>(true));
1240 auto const dict
= dinit
.toArray();
1241 VanillaDict::as(dict
.get())->onSetEvalScalar();
1242 auto const static_dict
= VanillaDict::CopyStatic(dict
.get());
1243 dicts
.push_back(make_persistent_array_like_tv(static_dict
));
1246 // In typical iterator usage, the constant pointer may point to an invalid
1247 // TypedValue that's off the end of the array being iterated over.
1248 auto const arr_type1
= Type::cns(dicts
[0]);
1249 auto const arr_type2
= Type::cns(dicts
[1]);
1250 auto const tv
= &dicts
[2];
1251 auto const spec_ptr_type
= (arr_type1
| arr_type2
).ptr(Ptr::Elem
);
1252 auto const base_ptr_type
= spec_ptr_type
.unspecialize();
1253 auto const cons_ptr_type
= Type::cns(tv
, spec_ptr_type
);
1255 EXPECT_EQ("PtrToElemStaticDict=Vanilla", spec_ptr_type
.toString());
1256 EXPECT_EQ("PtrToElemStaticDict", base_ptr_type
.toString());
1257 auto const str
= folly::format("PtrToElemStaticDict<TV: {}>", tv
).str();
1258 EXPECT_EQ(str
, cons_ptr_type
.toString());
1260 // The specialized ptr type is not constant. The constant ptr type is not
1261 // specialized, because we can't represent both.
1262 EXPECT_TRUE(spec_ptr_type
.isSpecialized());
1263 EXPECT_FALSE(spec_ptr_type
.hasConstVal());
1264 EXPECT_FALSE(base_ptr_type
.isSpecialized());
1265 EXPECT_FALSE(base_ptr_type
.hasConstVal());
1266 EXPECT_FALSE(cons_ptr_type
.isSpecialized());
1267 EXPECT_TRUE(cons_ptr_type
.hasConstVal());
1269 // Because of these representation issues, the intersection of these two
1270 // types should just return the constant pointer type alone.
1271 EXPECT_FALSE(cons_ptr_type
<= spec_ptr_type
);
1272 EXPECT_TRUE(cons_ptr_type
<= base_ptr_type
);
1273 EXPECT_EQ(cons_ptr_type
, cons_ptr_type
& spec_ptr_type
);
1274 EXPECT_EQ(cons_ptr_type
, spec_ptr_type
& cons_ptr_type
);
1275 EXPECT_EQ(base_ptr_type
, cons_ptr_type
| spec_ptr_type
);
1276 EXPECT_EQ(base_ptr_type
, spec_ptr_type
| cons_ptr_type
);