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 #ifndef incl_HHBBC_TYPE_SYSTEM_H_
17 #define incl_HHBBC_TYPE_SYSTEM_H_
23 #include <folly/Optional.h>
25 #include "hphp/util/copy-ptr.h"
26 #include "hphp/util/low-ptr.h"
28 #include "hphp/runtime/base/repo-auth-type.h"
29 #include "hphp/runtime/base/repo-auth-type-array.h"
30 #include "hphp/runtime/base/array-provenance.h"
32 #include "hphp/hhbbc/array-like-map.h"
33 #include "hphp/hhbbc/index.h"
34 #include "hphp/hhbbc/misc.h"
36 namespace HPHP
{ namespace HHBBC
{
40 //////////////////////////////////////////////////////////////////////
45 * Here's an unmaintainable ascii-art diagram:
50 * | | InitCell := Cell - Uninit
51 * Cls | ?X := X + InitNull
55 * Cls=c +-------------+--------+-------+-------+-----+
57 * Unc | | Obj Res Record
59 * | \ | | Obj<=c Obj<=WaitHandle
61 * / | InitUnc | | Obj=c WaitH<T>
66 * Null InitPrim | | | |
69 * Uninit InitNull | | SArr ... / CStr
89 * Some notes on some of the basic types:
93 * "Primitive" types---these can be represented in a TypedValue without a
94 * pointer to the heap.
98 * "Uncounted" types---values of these types don't require reference
103 * A WaitHandle that is known will either return a value of type T from
104 * its join() method (or Await), or else throw an exception.
108 * Arrays are divided along two dimensions: counted or uncounted, and empty
109 * or non-empty. Unions of either are allowed. The naming convention is
110 * {S,C,}Arr{N,E,}, where leaving out either bit means it's unknown along
111 * that dimension. All arrays are subtypes of the Arr type. The lattice
112 * here looks like this:
120 * +-------+---------------+
122 * | ArrN +-----+ ArrE |
124 * SArrN CArrN CArrE SArrE
126 * NOTE: Having SArr be a sibling of CArr is problematic. There is
127 * an assumption that types in the index only ever get more refined,
128 * but eg we might "know" that a type is CArr early on (because eg
129 * we stored a value to it, thus modifying it), but later we might
130 * know the value both before and after the modification, and just
131 * replace each with a static array. In fact, this is almost
132 * guaranteed to happen when building arrays from constants (not
133 * literals), because on the first pass we won't know the constant
134 * values, and will produce a CArr, but eventually we could figure
135 * them out, and produce an SArr. This means that in practice, we
136 * can't use CArr anywhere, because it might be improved to SArr,
137 * which is not a subtype. Even if we only generated CArr after all
138 * modifications are done (eg during the insert-assertions phase) we
139 * could still run into problems where we annotate an array as CArr
140 * but jit time analysis/optimization was able to produce a static
141 * array - so it doesn't appear to be useful, except as a superclass
144 * "Specialized" array types may be found as subtypes of any of the above
145 * types except SArrE and CArrE, or of optional versions of the above types
146 * (e.g. as a subtype of ?ArrN). The information about additional structure
147 * is dispayed in parenthesis, and probably best explained by some examples:
151 * Tuple-like static two-element array, with integer keys 0 and 1,
152 * containing a Bool and an Int with unknown values.
156 * An array of unknown countedness that is either empty, or a
157 * tuple-like array with two elements of types Int and Dbl.
161 * Non-empty reference counted array with contiguous zero-based integer
162 * keys, unknown size, values all are subtypes of Bool.
166 * Struct-like array with known fields "x" and "y" that have Int
167 * values, and no other fields. Struct-like arrays always have known
168 * string keys, and the type contains only those array values with
169 * exactly the given key set, in the order specified.
171 * Arr([SStr:InitCell])
173 * Possibly empty map-like array with unknown keys, but all
174 * non-reference counted strings, all values InitCell. In this case
175 * the array itself may or may not be static.
177 * Note that struct-like arrays will be subtypes of map-like arrays
180 * ArrN([Int:InitPrim])
182 * Map-like array with only integer keys (not-necessarily contiguous)
183 * and values that are all subtypes of InitPrim. Note that the keys
184 * *may* be contiguous integers, so for example Arr([InitPrim]) <:
185 * Arr([Int => InitPrim]).
187 * Arr([ArrKey:InitCell])
189 * Map-like array with either integer or string keys, and InitCell
190 * values, or empty. Essentially this is the most generic array that
191 * can't contain php references.
194 //////////////////////////////////////////////////////////////////////
196 enum trep
: uint64_t {
200 BInitNull
= 1ULL << 1,
205 BSStr
= 1ULL << 6, // static string
206 BCStr
= 1ULL << 7, // counted string
209 BSPArrE
= 1ULL << 9, // static empty "plain" array
210 BCPArrE
= 1ULL << 10, // counted empty "plain" array
211 BSPArrN
= 1ULL << 11, // static non-empty "plain" array
212 BCPArrN
= 1ULL << 12ULL, // counted non-empty "plain array"
214 BSVArrE
= 1ULL << 13, // static empty varray
215 BCVArrE
= 1ULL << 14, // counted empty varray
216 BSVArrN
= 1ULL << 15, // static non-empty varray
217 BCVArrN
= 1ULL << 16, // counted non-empty varray
219 BSDArrE
= 1ULL << 17, // static empty darray
220 BCDArrE
= 1ULL << 18, // counted empty darray
221 BSDArrN
= 1ULL << 19, // static non-empty darray
222 BCDArrN
= 1ULL << 20, // counted non-empty darray
224 BClsMeth
= 1ULL << 21, // ClassMethod
230 BSVecE
= 1ULL << 25, // static empty vec
231 BCVecE
= 1ULL << 26, // counted empty vec
232 BSVecN
= 1ULL << 27, // static non-empty vec
233 BCVecN
= 1ULL << 28, // counted non-empty vec
234 BSDictE
= 1ULL << 29, // static empty dict
235 BCDictE
= 1ULL << 30, // counted empty dict
236 BSDictN
= 1ULL << 31, // static non-empty dict
237 BCDictN
= 1ULL << 32, // counted non-empty dict
238 BSKeysetE
= 1ULL << 33, // static empty keyset
239 BCKeysetE
= 1ULL << 34, // counted empty keyset
240 BSKeysetN
= 1ULL << 35, // static non-empty keyset
241 BCKeysetN
= 1ULL << 36, // counted non-empty keyset
243 BRecord
= 1ULL << 37,
245 BSPArr
= BSPArrE
| BSPArrN
,
246 BCPArr
= BCPArrE
| BCPArrN
,
247 BPArrE
= BSPArrE
| BCPArrE
,
248 BPArrN
= BSPArrN
| BCPArrN
,
249 BPArr
= BPArrE
| BPArrN
,
251 BSVArr
= BSVArrE
| BSVArrN
,
252 BCVArr
= BCVArrE
| BCVArrN
,
253 BVArrE
= BSVArrE
| BCVArrE
,
254 BVArrN
= BSVArrN
| BCVArrN
,
255 BVArr
= BVArrE
| BVArrN
,
257 BSDArr
= BSDArrE
| BSDArrN
,
258 BCDArr
= BCDArrE
| BCDArrN
,
259 BDArrE
= BSDArrE
| BCDArrE
,
260 BDArrN
= BSDArrN
| BCDArrN
,
261 BDArr
= BDArrE
| BDArrN
,
263 BSArrE
= BSPArrE
| BSVArrE
| BSDArrE
,
264 BCArrE
= BCPArrE
| BCVArrE
| BCDArrE
,
265 BSArrN
= BSPArrN
| BSVArrN
| BSDArrN
,
266 BCArrN
= BCPArrN
| BCVArrN
| BCDArrN
,
268 BNull
= BUninit
| BInitNull
,
269 BBool
= BFalse
| BTrue
,
271 BStr
= BSStr
| BCStr
,
272 BSArr
= BSArrE
| BSArrN
,
273 BCArr
= BCArrE
| BCArrN
,
274 BArrE
= BSArrE
| BCArrE
,
275 BArrN
= BSArrN
| BCArrN
, // may have value / data
276 BArr
= BArrE
| BArrN
,
277 BSVec
= BSVecE
| BSVecN
,
278 BCVec
= BCVecE
| BCVecN
,
279 BVecE
= BSVecE
| BCVecE
,
280 BVecN
= BSVecN
| BCVecN
,
281 BVec
= BVecE
| BVecN
,
282 BSDict
= BSDictE
| BSDictN
,
283 BCDict
= BCDictE
| BCDictN
,
284 BDictE
= BSDictE
| BCDictE
,
285 BDictN
= BSDictN
| BCDictN
,
286 BDict
= BDictE
| BDictN
,
287 BSKeyset
= BSKeysetE
| BSKeysetN
,
288 BCKeyset
= BCKeysetE
| BCKeysetN
,
289 BKeysetE
= BSKeysetE
| BCKeysetE
,
290 BKeysetN
= BSKeysetN
| BCKeysetN
,
291 BKeyset
= BKeysetE
| BKeysetN
,
294 BOptTrue
= BInitNull
| BTrue
,
295 BOptFalse
= BInitNull
| BFalse
,
296 BOptBool
= BInitNull
| BBool
,
297 BOptInt
= BInitNull
| BInt
, // may have value
298 BOptDbl
= BInitNull
| BDbl
, // may have value
299 BOptNum
= BInitNull
| BNum
,
300 BOptSStr
= BInitNull
| BSStr
, // may have value
301 BOptCStr
= BInitNull
| BCStr
,
302 BOptStr
= BInitNull
| BStr
,
303 BOptSArrE
= BInitNull
| BSArrE
,
304 BOptCArrE
= BInitNull
| BCArrE
,
305 BOptSArrN
= BInitNull
| BSArrN
, // may have value / data
306 BOptCArrN
= BInitNull
| BCArrN
, // may have value / data
307 BOptSArr
= BInitNull
| BSArr
, // may have value / data
308 BOptCArr
= BInitNull
| BCArr
, // may have value / data
309 BOptArrE
= BInitNull
| BArrE
, // may have value / data
310 BOptArrN
= BInitNull
| BArrN
, // may have value / data
311 BOptArr
= BInitNull
| BArr
, // may have value / data
312 BOptObj
= BInitNull
| BObj
, // may have data
313 BOptRes
= BInitNull
| BRes
,
314 BOptFunc
= BInitNull
| BFunc
,
315 BOptCls
= BInitNull
| BCls
,
316 BOptClsMeth
= BInitNull
| BClsMeth
,
317 BOptSVecE
= BInitNull
| BSVecE
,
318 BOptCVecE
= BInitNull
| BCVecE
,
319 BOptSVecN
= BInitNull
| BSVecN
,
320 BOptCVecN
= BInitNull
| BCVecN
,
321 BOptSVec
= BInitNull
| BSVec
,
322 BOptCVec
= BInitNull
| BCVec
,
323 BOptVecE
= BInitNull
| BVecE
,
324 BOptVecN
= BInitNull
| BVecN
,
325 BOptVec
= BInitNull
| BVec
,
326 BOptSDictE
= BInitNull
| BSDictE
,
327 BOptCDictE
= BInitNull
| BCDictE
,
328 BOptSDictN
= BInitNull
| BSDictN
,
329 BOptCDictN
= BInitNull
| BCDictN
,
330 BOptSDict
= BInitNull
| BSDict
,
331 BOptCDict
= BInitNull
| BCDict
,
332 BOptDictE
= BInitNull
| BDictE
,
333 BOptDictN
= BInitNull
| BDictN
,
334 BOptDict
= BInitNull
| BDict
,
335 BOptSKeysetE
= BInitNull
| BSKeysetE
,
336 BOptCKeysetE
= BInitNull
| BCKeysetE
,
337 BOptSKeysetN
= BInitNull
| BSKeysetN
,
338 BOptCKeysetN
= BInitNull
| BCKeysetN
,
339 BOptSKeyset
= BInitNull
| BSKeyset
,
340 BOptCKeyset
= BInitNull
| BCKeyset
,
341 BOptKeysetE
= BInitNull
| BKeysetE
,
342 BOptKeysetN
= BInitNull
| BKeysetN
,
343 BOptKeyset
= BInitNull
| BKeyset
,
344 BOptRecord
= BInitNull
| BRecord
,
346 BOptSPArrE
= BInitNull
| BSPArrE
,
347 BOptCPArrE
= BInitNull
| BCPArrE
,
348 BOptSPArrN
= BInitNull
| BSPArrN
,
349 BOptCPArrN
= BInitNull
| BCPArrN
,
350 BOptSPArr
= BInitNull
| BSPArr
,
351 BOptCPArr
= BInitNull
| BCPArr
,
352 BOptPArrE
= BInitNull
| BPArrE
,
353 BOptPArrN
= BInitNull
| BPArrN
,
354 BOptPArr
= BInitNull
| BPArr
,
356 BOptSVArrE
= BInitNull
| BSVArrE
,
357 BOptCVArrE
= BInitNull
| BCVArrE
,
358 BOptSVArrN
= BInitNull
| BSVArrN
,
359 BOptCVArrN
= BInitNull
| BCVArrN
,
360 BOptSVArr
= BInitNull
| BSVArr
,
361 BOptCVArr
= BInitNull
| BCVArr
,
362 BOptVArrE
= BInitNull
| BVArrE
,
363 BOptVArrN
= BInitNull
| BVArrN
,
364 BOptVArr
= BInitNull
| BVArr
,
366 BOptSDArrE
= BInitNull
| BSDArrE
,
367 BOptCDArrE
= BInitNull
| BCDArrE
,
368 BOptSDArrN
= BInitNull
| BSDArrN
,
369 BOptCDArrN
= BInitNull
| BCDArrN
,
370 BOptSDArr
= BInitNull
| BSDArr
,
371 BOptCDArr
= BInitNull
| BCDArr
,
372 BOptDArrE
= BInitNull
| BDArrE
,
373 BOptDArrN
= BInitNull
| BDArrN
,
374 BOptDArr
= BInitNull
| BDArr
,
376 BUncArrKey
= BInt
| BSStr
,
377 BArrKey
= BUncArrKey
| BCStr
,
378 BOptUncArrKey
= BInitNull
| BUncArrKey
,
379 BOptArrKey
= BInitNull
| BArrKey
,
381 BStrLike
= BFunc
| BStr
| BCls
,
382 BUncStrLike
= BFunc
| BSStr
| BCls
,
384 BOptStrLike
= BInitNull
| BStrLike
,
385 BOptUncStrLike
= BInitNull
| BUncStrLike
,
387 BInitPrim
= BInitNull
| BBool
| BNum
| BFunc
| BCls
|
388 (use_lowptr
? BClsMeth
: 0),
390 BPrim
= BInitPrim
| BUninit
,
391 BInitUnc
= BInitPrim
| BSStr
| BSArr
| BSVec
| BSDict
| BSKeyset
,
392 BUnc
= BInitUnc
| BUninit
,
393 BInitCell
= BInitNull
| BBool
| BInt
| BDbl
| BStr
| BArr
| BObj
| BRes
|
394 BVec
| BDict
| BKeyset
| BFunc
| BCls
| BClsMeth
| BRecord
,
395 BCell
= BUninit
| BInitCell
,
397 BTop
= static_cast<uint64_t>(-1),
400 constexpr trep
operator~(trep a
) {
401 return static_cast<trep
>(~static_cast<int64_t>(a
));
404 constexpr trep
operator&(trep a
, trep b
) {
405 return static_cast<trep
>(static_cast<int64_t>(a
) & b
);
408 constexpr trep
operator|(trep a
, trep b
) {
409 return static_cast<trep
>(static_cast<int64_t>(a
) | b
);
412 constexpr const trep
& operator&=(trep
&a
, trep b
) {
417 constexpr const trep
& operator|=(trep
&a
, trep b
) {
422 // Useful constants. Don't put them in the enum itself, because they
423 // can't actually occur, but are convenient masks.
424 constexpr auto BArrLikeE
= BArrE
| BVecE
| BDictE
| BKeysetE
;
425 constexpr auto BArrLikeN
= BArrN
| BVecN
| BDictN
| BKeysetN
;
426 constexpr auto BArrLike
= BArrLikeE
| BArrLikeN
;
427 constexpr auto BSArrLike
= BSArr
| BSVec
| BSDict
| BSKeyset
;
430 DT(Str, SString, sval) \
431 DT(Int, int64_t, ival) \
432 DT(Dbl, double, dval) \
433 DT(ArrLikeVal, SArray, aval) \
434 DT(Obj, DObj, dobj) \
435 DT(Cls, DCls, dcls) \
436 DT(ArrLikePacked, copy_ptr<DArrLikePacked>, packed) \
437 DT(ArrLikePackedN, copy_ptr<DArrLikePackedN>, packedn) \
438 DT(ArrLikeMap, copy_ptr<DArrLikeMap>, map) \
439 DT(ArrLikeMapN, copy_ptr<DArrLikeMapN>, mapn)
441 // Tag for what kind of specialized data a Type object has.
442 enum class DataTag
: uint8_t {
444 #define DT(name,...) name,
449 //////////////////////////////////////////////////////////////////////
452 * Information about a class type. The class is either exact or a
453 * subtype of the supplied class.
456 enum Tag
: uint16_t { Exact
, Sub
};
458 DCls(Tag type
, res::Class cls
)
469 * Information about a specific object type. The class is either
470 * exact or a subtype of the supplied class.
472 * If the class is WaitHandle, we can also carry a type that joining
473 * the wait handle will produce.
476 enum Tag
: uint16_t { Exact
, Sub
};
478 DObj(Tag type
, res::Class cls
)
486 copy_ptr
<Type
> whType
;
489 struct DArrLikePacked
;
490 struct DArrLikePackedN
;
493 using MapElems
= ArrayLikeMap
<Cell
>;
498 * A provenance tag as tracked on a DArrLike{Packed,Map}. (and, at runtime, on
499 * dicts and vecs.) The provenance tag on an array contains a file and line
500 * nubmer where that array is 'from' (ideally, where the array was
501 * allocated--for static arrays the srcloc where the array is first referenced)
503 * This is tracked here in hhbbc both because we manipulate and create new
506 * If the runtime option EvalArrayProvenance is not set, all ProvTags should be
507 * equal to the top of the lattice (folly::none)
509 * The absence of a value here (folly::none) means the array type could have a
510 * provenance tag from anywhere, or no tag at all. (i.e. its provenance is
511 * unknown completely).
513 * This information forms a sublattice like:
518 * t_1 t_2 ... t_n (specific arrprov::Tag's)
519 * \____ | ___________/
521 * bottom (unrepresentable)
523 * If we would produce a 'bottom' provenance tag, (i.e. in intersectProvTag)
524 * we widen the result to 'top'
526 using ProvTag
= folly::Optional
<arrprov::Tag
>;
528 enum class Emptiness
{
534 enum class ThrowMode
{
542 //////////////////////////////////////////////////////////////////////
545 Type() : m_bits(BTop
) {
546 assert(checkInvariants());
548 explicit Type(trep t
) : m_bits(t
) {
549 assert(checkInvariants());
552 Type(const Type
&) noexcept
;
553 Type(Type
&&) noexcept
;
554 Type
& operator=(const Type
&) noexcept
;
555 Type
& operator=(Type
&&) noexcept
;
559 * Exact equality or inequality of types, and hashing.
561 bool operator==(const Type
& o
) const;
562 bool operator!=(const Type
& o
) const { return !(*this == o
); }
565 const Type
& operator |= (const Type
& other
);
566 const Type
& operator |= (Type
&& other
);
567 const Type
& operator &= (const Type
& other
);
568 const Type
& operator &= (Type
&& other
);
571 * Returns true if this type is equivalently refined, more refined or strictly
572 * more refined than `o`. This is similar to the `==` and subtype operations
573 * defined below, except they take into account if a type is tagged as a
576 bool equivalentlyRefined(const Type
& o
) const;
577 bool moreRefined(const Type
& o
) const;
578 bool strictlyMoreRefined(const Type
& o
) const;
581 * Returns true if this type is definitely going to be a subtype or a strict
582 * subtype of `o' at runtime. If this function returns false, this may
583 * still be a subtype of `o' at runtime, it just may not be known.
585 bool subtypeOf(const Type
& o
) const;
586 bool strictSubtypeOf(const Type
& o
) const;
589 * Similar, but only check the trep (same as subtypeOf(Type{bits}),
592 bool subtypeOf(trep bits
) const { return (m_bits
& bits
) == m_bits
; }
593 bool subtypeOrNull(trep bits
) const { return subtypeOf(bits
| BNull
); }
596 * Subtype of any of the list of types.
598 template<class... Types
>
599 bool subtypeOfAny(const Type
& t
, Types
... ts
) const {
600 return subtypeOf(t
) || subtypeOfAny(ts
...);
602 bool subtypeOfAny() const { return false; }
604 template<bool contextSensitive
>
605 bool equivImpl(const Type
& o
) const;
606 template<bool contextSensitive
>
607 bool subtypeOfImpl(const Type
& o
) const;
610 * Returns whether there are any values of this type that are also
611 * values of the type `o'.
612 * When this function returns false, it is known that this type
613 * must not be in any subtype relationship with the argument Type 'o'.
614 * When true is returned the two types may still be unrelated but it is
615 * not possible to tell.
616 * Essentially this function can conservatively return true but must be
617 * precise when returning false.
619 bool couldBe(const Type
& o
) const;
620 bool couldBe(trep bits
) const { return m_bits
& bits
; }
623 * Could-be any of the list of types.
625 template<class... Types
>
626 bool couldBeAny(const Type
& t
, Types
... ts
) const {
627 return couldBe(t
) || couldBeAny(ts
...);
629 bool couldBeAny() const { return false; }
632 enum { None
, Empty
, Packed
, Struct
, Mixed
} cat
;
637 friend folly::Optional
<int64_t> arr_size(const Type
& t
);
638 friend ArrayCat
categorize_array(const Type
& t
);
639 friend CompactVector
<LSString
> get_string_keys(const Type
& t
);
640 friend Type
wait_handle(const Index
&, Type
);
641 friend bool is_specialized_wait_handle(const Type
&);
642 friend bool is_specialized_array_like(const Type
& t
);
643 friend bool is_specialized_obj(const Type
&);
644 friend bool is_specialized_cls(const Type
&);
645 friend bool is_specialized_string(const Type
&);
646 friend Type
wait_handle_inner(const Type
&);
647 friend Type
sval(SString
);
648 friend Type
sval_nonstatic(SString
);
649 friend Type
ival(int64_t);
650 friend Type
dval(double);
651 friend Type
aval(SArray
);
652 friend Type
subObj(res::Class
);
653 friend Type
objExact(res::Class
);
654 friend Type
subCls(res::Class
);
655 friend Type
clsExact(res::Class
);
656 friend Type
rname(SString
);
657 friend Type
packed_impl(trep
, std::vector
<Type
>, ProvTag
);
658 friend Type
packedn_impl(trep
, Type
);
659 friend Type
map_impl(trep
, MapElems
, ProvTag
);
660 friend Type
mapn_impl(trep bits
, Type k
, Type v
, ProvTag
);
661 friend Type
mapn_impl_from_map(trep bits
, Type k
, Type v
, ProvTag
);
662 friend DObj
dobj_of(const Type
&);
663 friend DCls
dcls_of(Type
);
664 friend SString
sval_of(const Type
&);
665 friend Type
union_of(Type
, Type
);
666 friend Type
intersection_of(Type
, Type
);
667 friend void widen_type_impl(Type
&, uint32_t);
668 friend Type
widen_type(Type
);
669 friend Type
widening_union(const Type
&, const Type
&);
670 friend Type
promote_emptyish(Type
, Type
);
671 friend Emptiness
emptiness(const Type
&);
672 friend Type
opt(Type
);
673 friend Type
unopt(Type
);
674 friend Type
unnullish(Type
);
675 friend bool is_opt(const Type
&);
676 friend bool is_nullish(const Type
&);
677 friend Type
project_data(Type t
, trep bits
);
678 template<typename R
, bool>
679 friend R
tvImpl(const Type
&);
680 friend Type
scalarize(Type t
);
681 friend folly::Optional
<size_t> array_size(const Type
& t
);
682 friend folly::Optional
<std::pair
<Type
,Type
>>
683 array_get_by_index(const Type
& t
, ssize_t index
);
685 friend Type
return_with_context(Type
, Type
);
686 friend Type
setctx(Type
, bool);
687 friend Type
unctx(Type
);
688 friend std::string
show(const Type
&);
689 friend ArrKey
disect_array_key(const Type
&);
690 friend std::pair
<Type
,bool> arr_val_elem(const Type
& aval
, const ArrKey
& key
);
691 friend std::pair
<Type
,bool> arr_map_elem(const Type
& map
, const ArrKey
& key
);
692 friend std::pair
<Type
,bool> arr_packed_elem(const Type
& pack
,
694 friend std::pair
<Type
,bool> arr_packedn_elem(const Type
& pack
,
696 friend std::pair
<Type
,ThrowMode
> array_like_elem(const Type
& arr
,
698 const Type
& defaultTy
);
699 friend std::pair
<Type
,ThrowMode
> array_like_set(Type arr
,
703 friend std::pair
<Type
,Type
> array_like_newelem(Type arr
, const Type
& val
,
705 friend bool arr_map_set(Type
& map
, const ArrKey
& key
,
706 const Type
& val
, ProvTag src
);
707 friend bool arr_packed_set(Type
& pack
, const ArrKey
& key
,
710 friend bool arr_packedn_set(Type
& pack
, const ArrKey
& key
,
711 const Type
& val
, bool maybeEmpty
);
712 friend bool arr_mapn_set(Type
& map
, const ArrKey
& key
, const Type
& val
);
713 friend Type
arr_map_newelem(Type
& map
, const Type
& val
, ProvTag src
);
714 friend IterTypes
iter_types(const Type
&);
715 friend RepoAuthType
make_repo_type_arr(ArrayTypeTable::Builder
&,
718 friend struct ArrKey
disect_vec_key(const Type
&);
719 friend struct ArrKey
disect_strict_key(const Type
&);
721 friend Type
spec_array_like_union(Type
&, Type
&, trep
, trep
);
722 friend Type
vec_val(SArray
);
723 friend Type
vec_empty(ProvTag
);
724 friend Type
some_vec_empty(ProvTag
);
725 friend Type
dict_val(SArray
);
726 friend Type
dict_empty(ProvTag
);
727 friend Type
some_dict_empty(ProvTag
);
728 friend Type
keyset_val(SArray
);
729 friend bool could_contain_objects(const Type
&);
730 friend bool could_copy_on_write(const Type
&);
731 friend Type
loosen_staticness(Type
);
732 friend Type
loosen_dvarrayness(Type
);
733 friend Type
loosen_provenance(Type
);
734 friend Type
loosen_values(Type
);
735 friend Type
loosen_emptiness(Type
);
736 friend Type
add_nonemptiness(Type
);
737 friend Type
assert_emptiness(Type
);
738 friend Type
assert_nonemptiness(Type
);
739 friend Type
set_trep(Type
&, trep
);
740 friend Type
remove_uninit(Type t
);
741 friend Type
to_cell(Type t
);
742 friend bool inner_types_might_raise(const Type
& t1
, const Type
& t2
);
748 #define DT(tag_name,type,name) type name;
753 template<class Ret
, class T
, class Function
>
757 static Type
unctxHelper(Type
, bool&);
758 static Type
unionArrLike(Type a
, Type b
);
759 template<class Ret
, class T
, class Function
>
760 DDHelperFn
<Ret
,T
,Function
> ddbind(const Function
& f
, const T
& t
) const;
761 template<class Ret
, class T
, class Function
>
762 Ret
dd2nd(const Type
&, DDHelperFn
<Ret
,T
,Function
>) const;
763 template<class Function
> typename
Function::result_type
764 dualDispatchDataFn(const Type
&, Function
) const;
765 bool hasData() const;
766 template<bool contextSensitive
>
767 bool equivData(const Type
&) const;
768 template<bool contextSensitive
>
769 bool subtypeData(const Type
&) const;
770 bool couldBeData(const Type
&) const;
771 bool checkInvariants() const;
772 ProvTag
getProvTag() const;
776 DataTag m_dataTag
= DataTag::None
;
780 //////////////////////////////////////////////////////////////////////
783 folly::Optional
<int64_t> i
;
784 folly::Optional
<SString
> s
;
786 bool mayThrow
= false;
788 folly::Optional
<Cell
> tv() const {
791 return make_tv
<KindOfInt64
>(*i
);
794 return make_tv
<KindOfPersistentString
>(*s
);
800 struct DArrLikePacked
{
801 explicit DArrLikePacked(std::vector
<Type
> elems
, ProvTag tag
)
802 : elems(std::move(elems
))
806 std::vector
<Type
> elems
;
810 struct DArrLikePackedN
{
811 explicit DArrLikePackedN(Type t
) : type(std::move(t
)) {}
817 explicit DArrLikeMap(MapElems map
, ProvTag tag
)
818 : map(std::move(map
))
825 struct DArrLikeMapN
{
826 explicit DArrLikeMapN(Type key
, Type val
)
827 : key(std::move(key
))
828 , val(std::move(val
))
834 //////////////////////////////////////////////////////////////////////
969 #define X(y) extern const Type T##y;
973 // These are treps that have B* names, but which are not "predefined"
974 // types. They are only allowed in combination with the corresponding
976 #define NON_TYPES(X) \
1022 //////////////////////////////////////////////////////////////////////
1025 * Return WaitH<T> for a type t.
1027 Type
wait_handle(const Index
&, Type t
);
1030 * Return T from a WaitH<T>.
1032 * Pre: is_specialized_handle(t);
1034 Type
wait_handle_inner(const Type
& t
);
1037 * Create Types that represent constant values.
1043 Type
vec_val(SArray
);
1044 Type
dict_val(SArray
);
1045 Type
keyset_val(SArray
);
1046 Type
sval_nonstatic(SString
);
1049 * Create static empty array or string types.
1053 Type
aempty_varray();
1054 Type
aempty_darray();
1055 Type
vec_empty(ProvTag pt
= folly::none
);
1056 Type
dict_empty(ProvTag pt
= folly::none
);
1057 Type
keyset_empty();
1060 * Create an any-countedness empty array/vec/dict type.
1063 Type
some_aempty_darray();
1064 Type
some_vec_empty(ProvTag pt
= folly::none
);
1065 Type
some_dict_empty(ProvTag pt
= folly::none
);
1066 Type
some_keyset_empty();
1069 * Create types for objects or classes with some known constraint on
1070 * which res::Class is associated with them.
1072 Type
subObj(res::Class
);
1073 Type
objExact(res::Class
);
1074 Type
subCls(res::Class
);
1075 Type
clsExact(res::Class
);
1078 * Packed array types with known size.
1082 Type
arr_packed(std::vector
<Type
> v
);
1083 Type
arr_packed_varray(std::vector
<Type
> v
);
1084 Type
sarr_packed(std::vector
<Type
> v
);
1087 * Packed array types of unknown size.
1089 * Note that these types imply the arrays are non-empty.
1091 Type
arr_packedn(Type
);
1092 Type
sarr_packedn(Type
);
1095 * Struct-like arrays.
1099 Type
arr_map(MapElems m
);
1100 Type
arr_map_darray(MapElems m
);
1101 Type
sarr_map(MapElems m
);
1106 Type
arr_mapn(Type k
, Type v
);
1107 Type
sarr_mapn(Type k
, Type v
);
1110 * vec types with known size.
1114 Type
vec(std::vector
<Type
> v
, ProvTag
);
1115 Type
svec(std::vector
<Type
> v
, ProvTag
);
1118 * Vec type of unknown size.
1124 * Struct-like dicts.
1128 Type
dict_map(MapElems m
, ProvTag
);
1131 * Dict with key/value types.
1133 Type
dict_n(Type
, Type
, ProvTag
);
1134 Type
sdict_n(Type
, Type
, ProvTag
);
1137 * Keyset with key (same as value) type.
1139 Type
keyset_n(Type
);
1140 Type
ckeyset_n(Type
);
1143 * Keyset from MapElems
1145 inline Type
keyset_map(MapElems m
) {
1146 return map_impl(BKeysetN
, std::move(m
), folly::none
);
1150 * Create the optional version of the Type t.
1152 * Pre: there must be an optional version of the type t.
1157 * Return the non-optional version of the Type t.
1164 * Returns whether a given type is a subtype of one of the predefined
1165 * optional types. (Note that this does not include types like
1166 * TInitUnc---it's only the TOpt* types.)
1168 bool is_opt(const Type
& t
);
1171 * Return t with BNull removed from its trep.
1173 * Pre: is_nullish(t)
1175 Type
unnullish(Type t
);
1178 * Returns whether a given type couldBe TNull, and would still be
1179 * predefined if BNull was removed from its trep.
1181 bool is_nullish(const Type
& t
);
1184 * Improves the type `t` given the current context. This returns the
1185 * intersection of the type `t` with the `context` if the `context` is a valid
1186 * class or object, and `t` is tagged as being the context. If `context` is
1187 * a class we will first convert it to an object. This returns an optional type
1188 * if `t` was optional.
1190 Type
return_with_context(Type t
, Type context
);
1193 * If `to` is false. This is an identity operation. If `to` is true, and
1194 * `t` is a specialized object or class, this will return `t` tagged as a
1197 Type
setctx(Type t
, bool to
= true);
1200 * This removes any context tags in the type `t`, even if nested inside other
1206 * Discards any data associated with `t` that isn't valid for the given trep
1208 * At the moment this will do nothing beyond removing empty ArrLikeDatas from
1209 * types that used to only have ArrE bits set but now have a ArrN bit set
1211 Type
project_data(Type t
, trep bits
);
1214 * Refinedness equivalence checks.
1216 bool equivalently_refined(const Type
&, const Type
&);
1220 typename
= std::enable_if
<
1221 std::is_same
<typename
Iterable::value_type
, Type
>::value
1224 bool equivalently_refined(const Iterable
& a
, const Iterable
& b
) {
1225 if (a
.size() != b
.size()) return false;
1226 for (auto ita
= a
.begin(), itb
= b
.begin(); ita
!= a
.end(); ++ita
, ++itb
) {
1227 if (!equivalently_refined(*ita
, *itb
)) return false;
1233 * Returns true if type 't' represents a "specialized" object, that is an
1234 * object of a known class, or an optional object of a known class.
1236 bool is_specialized_obj(const Type
&);
1239 * Returns true if type 't' represents a "specialized" class---i.e. a class
1240 * with a DCls structure.
1242 bool is_specialized_cls(const Type
&);
1245 * Returns whether `t' is a WaitH<T> or ?WaitH<T> for some T.
1247 * Note that this function returns false for Obj<=WaitHandle with no
1248 * tracked inner type.
1250 bool is_specialized_wait_handle(const Type
& t
);
1253 * Returns whether `t' is a one of the array like types, or
1254 * an optional version of one of those types. That is, with
1255 * either a constant value or some (maybe partially) known shape.
1257 bool is_specialized_array(const Type
& t
);
1258 bool is_specialized_vec(const Type
& t
);
1259 bool is_specialized_dict(const Type
& t
);
1260 bool is_specialized_keyset(const Type
& t
);
1263 * Returns the best known instantiation of a class type. Or returns the
1266 * Pre: t.subypeOfAny(TObj, TCls)
1268 Type
toobj(const Type
& t
);
1271 * Returns the best known TCls subtype for an object type. Otherwise return
1272 * the passed in type.
1274 Type
objcls(const Type
& t
);
1277 * If the type t has a known constant value, return it as a Cell.
1278 * Otherwise return folly::none.
1280 * The returned Cell can only contain non-reference-counted types.
1282 folly::Optional
<Cell
> tv(const Type
& t
);
1285 * If the type t has a known constant value, return it as a Cell.
1286 * Otherwise return folly::none.
1288 * The returned Cell may contain reference-counted types.
1290 * You are responsible for any required ref-counting.
1292 folly::Optional
<Cell
> tvNonStatic(const Type
& t
);
1295 * If the type t has a known constant value, return true.
1296 * Otherwise return false.
1298 bool is_scalar(const Type
& t
);
1301 * Return the canonical scalar type for t - equivalent to
1302 * from_cell(*tv(t)).
1304 * This can be used to ensure that the arguments in a CallContext are
1305 * canonicalized, so that immaterial changes to them (eg TArrN ->
1306 * TSArrN or DArrLikeMap -> DArrLikeVal) don't affect which entry gets
1309 * pre: is_scalar(t).
1311 Type
scalarize(Type t
);
1314 * If t represents an array, and we know its size, return it.
1316 folly::Optional
<size_t> array_size(const Type
& t
);
1319 * If t represents an array, and we know the index'th element (by
1320 * iteration order), return the key/value pair.
1322 * Negative values of index work backwards from the last element.
1324 folly::Optional
<std::pair
<Type
,Type
>>
1325 array_get_by_index(const Type
& t
, ssize_t index
);
1328 * Get the type in our typesystem that corresponds to an hhbc
1331 * Pre: op != IsTypeOp::Scalar
1333 Type
type_of_istype(IsTypeOp op
);
1336 * Get the hhbc IsTypeOp that corresponds to the type in our typesystem.
1337 * Returns folly::none if no matching IsTypeOp is found.
1339 folly::Optional
<IsTypeOp
> type_to_istypeop(const Type
& t
);
1342 * Get the type in our typesystem that corresponds to type given by the
1343 * potentially unresolved type structure.
1344 * Returns folly::none if the type structure is unresolved or
1345 * no matching Type is found.
1348 folly::Optional
<Type
> type_of_type_structure(SArray ts
);
1351 * Return the DObj structure for a strict subtype of TObj or TOptObj.
1353 * Pre: is_specialized_obj(t)
1355 DObj
dobj_of(const Type
& t
);
1358 * Return the DCls structure for a strict subtype of TCls.
1360 * Pre: is_specialized_cls(t)
1362 DCls
dcls_of(Type t
);
1365 * Return the SString for a strict subtype of TStr.
1367 * Pre: is_specialized_string(t)
1369 SString
sval_of(const Type
& t
);
1372 * Create a Type from a Cell.
1374 * Pre: the cell must contain a non-reference-counted type.
1375 * Post: returned type is a subtype of TUnc
1377 Type
from_cell(Cell tv
);
1380 * Create a Type from a DataType. KindOfString and KindOfPersistentString
1381 * are both treated as TStr.
1383 * Pre: dt is one of the DataTypes that actually represent php values
1384 * (or KindOfUninit).
1386 Type
from_DataType(DataType dt
);
1389 * Create a Type from a builtin type specification string.
1391 * This is used for HNI class properties. We assume that these are
1392 * accurate. `s' may be nullptr.
1394 Type
from_hni_constraint(SString s
);
1397 * Make a type that represents values from the intersection of the
1400 Type
intersection_of(Type a
, Type b
);
1403 * Make a type that represents values from either of the supplied
1406 * Importantly, note that there are infinitely long chains of array
1407 * types that continue to become less specialized, so chains of
1408 * union_of operations are not guaranteed to reach a stable point in
1411 Type
union_of(Type a
, Type b
);
1416 * This operation returns a type T, such that a is a subtype of T, b
1417 * is a subtype of T, and union_of(a, b) is a subtype of T. The
1418 * widening union also has the property that every possible chain of
1419 * successive applications of the function eventually reaches a stable
1422 * This is currently implemented by unioning the types, then applying
1423 * widen_type() to the result.
1425 * For portions of our analysis that rely on growing types reaching
1426 * stable points for termination, this function must occasionally be
1427 * used instead of union_of to guarantee termination. See details in
1430 Type
widening_union(const Type
& a
, const Type
& b
);
1433 * Widen a type to one which has a finite chain under the union operator. This
1434 * generally involves restricting the type's nesting depth to a fixed limit and
1435 * preventing a specialized array type from growing larger unbounded.
1437 Type
widen_type(Type t
);
1440 * A sort of union operation that also attempts to remove "emptyish" types from
1441 * union_of(a, b). This is useful for promoting emptyish types (sempty(),
1442 * false, and null) to stdClass or to arrays, in member instructions.
1444 * This function currently doesn't give specific guarantees about exactly when
1445 * the emptyish types will not be part of the return type (informally it only
1446 * happens in the "easy" cases right now), so you should not use it in
1447 * situations where union_of(a, b) would not also be correct.
1449 Type
promote_emptyish(Type a
, Type b
);
1453 * Returns what we know about the emptiness of the type.
1455 Emptiness
emptiness(const Type
&);
1458 * Returns whether a Type could hold an object that has a custom
1459 * boolean conversion function.
1461 bool could_have_magic_bool_conversion(const Type
&);
1464 * Returns the smallest type that `a' is a subtype of, from the
1465 * following set: TInitCell, TUninit.
1467 * Pre: `a' is a subtype of TCell.
1469 Type
stack_flav(Type a
);
1472 * Discard any countedness information about the type. Force any type
1473 * (recursively) which contains only static or counted variants to contain
1474 * both. Doesn't change the type otherwise.
1476 Type
loosen_staticness(Type
);
1479 * Discard any specific knowledge about whether the type is a d/varray. Force
1480 * any type which might contain any sub-types of PArr, VArr, or DArr to contain
1481 * Arr, while keeping the same staticness and emptiness information.
1483 Type
loosen_dvarrayness(Type
);
1486 * Discard any specific provenance tag on this type and any sub-arrays
1488 Type
loosen_provenance(Type
);
1491 * Force any type which might contain any sub-types of Arr, Vec, Dict, and
1492 * Keyset to contain Arr, Vec, Dict, and Keyset. This is needed for some
1493 * operations whose effects on arrays cannot be predicted. Doesn't change the
1496 Type
loosen_arrays(Type
);
1499 * Drop any data from the type (except for object class information) and force
1500 * TTrue or TFalse to TBool. Doesn't change the type otherwise.
1502 Type
loosen_values(Type t
);
1505 * Discard any emptiness information about the type. Force any type which
1506 * contains only empty or non-empty variants to contain both. Doesn't change the
1509 Type
loosen_emptiness(Type t
);
1512 * Loosens staticness, emptiness, and values from the type. This forces a type
1513 * to its most basic form (except for object class information).
1515 Type
loosen_all(Type t
);
1518 * If t contains TUninit, returns the best type we can that contains
1519 * at least everything t contains, but doesn't contain TUninit. Note
1520 * that this function will return TBottom for TUninit.
1522 Type
remove_uninit(Type t
);
1525 * If t is not a TCell, returns TInitCell. Otherwise, if t contains
1526 * TUninit, return union_of(remove_uninit(t), TInitCell).
1528 Type
to_cell(Type t
);
1531 * Add non-empty variants of the type to the type if not already
1532 * present. Doesn't change the type otherwise.
1534 Type
add_nonemptiness(Type t
);
1537 * Produced the most refined type possible, given that
1538 * t passed/failed an emptiness check.
1540 Type
assert_emptiness(Type
);
1541 Type
assert_nonemptiness(Type
);
1544 * (array|vec|dict|keyset)_elem
1546 * Returns the best known type of an array inner element given a type
1547 * for the key. The returned type is always a subtype of TInitCell.
1549 * The returned type will be TBottom if the operation will always throw.
1550 * ThrowMode indicates what kind of failures may occur.
1552 * Pre: first arg is a subtype of TArr, TVec, TDict, TKeyset respectively.
1554 std::pair
<Type
,ThrowMode
> array_elem(const Type
& arr
, const Type
& key
,
1555 const Type
& defaultTy
= TInitNull
);
1556 std::pair
<Type
, ThrowMode
> vec_elem(const Type
& vec
, const Type
& key
,
1557 const Type
& defaultTy
= TBottom
);
1558 std::pair
<Type
, ThrowMode
> dict_elem(const Type
& dict
, const Type
& key
,
1559 const Type
& defaultTy
= TBottom
);
1560 std::pair
<Type
, ThrowMode
> keyset_elem(const Type
& keyset
, const Type
& key
,
1561 const Type
& defaultTy
= TBottom
);
1564 * (array|vec|dict|keyset)_set
1566 * Perform an array-like set on types. Returns a type that represents the
1567 * effects of arr[key] = val.
1569 * The returned type will be TBottom if the operation will always throw.
1570 * ThrowMode indicates what kind of failures may occur.
1572 * Pre: first arg is a subtype of TArr, TVec, TDict, TKeyset respectively.
1574 std::pair
<Type
, ThrowMode
> array_set(Type arr
, const Type
& key
,
1575 const Type
& val
, ProvTag src
);
1576 std::pair
<Type
, ThrowMode
> vec_set(Type vec
, const Type
& key
, const Type
& val
,
1578 std::pair
<Type
, ThrowMode
> dict_set(Type dict
, const Type
& key
,
1579 const Type
& val
, ProvTag src
);
1580 std::pair
<Type
, ThrowMode
> keyset_set(Type keyset
, const Type
& key
,
1584 * (array|vec|dict|keyset)_newelem
1586 * Perform a newelem operation on an array-like type. Returns an
1587 * array that contains a new pushed-back element with the supplied
1588 * value, in the sense of arr[] = val, and the best known type of the
1589 * key that was added.
1591 * Pre: first arg is a subtype of TArr, TVec, TDict, TKeyset respectively.
1593 std::pair
<Type
,Type
> array_newelem(Type arr
, const Type
& val
, ProvTag src
);
1594 std::pair
<Type
,Type
> vec_newelem(Type vec
, const Type
& val
, ProvTag src
);
1595 std::pair
<Type
,Type
> dict_newelem(Type dict
, const Type
& val
, ProvTag src
);
1596 std::pair
<Type
,Type
> keyset_newelem(Type keyset
, const Type
& val
);
1599 * Return the best known information for iteration of the supplied type. This is
1600 * only intended for non-mutable iteration, so the returned types are at worst
1606 // The number of elements we're iterating over:
1608 Empty
, // No elements
1609 Single
, // Exactly one element
1610 ZeroOrOne
, // Less than 2 elements
1611 NonEmpty
, // Unknown upper bound, but non-empty
1612 Any
// Nothing known
1615 // Can a IterInit[K] op throw on this iterator?
1616 bool mayThrowOnInit
;
1617 // Can a IterNext[K] op throw on this iterator? Can only happen for object
1619 bool mayThrowOnNext
;
1621 IterTypes
iter_types(const Type
&);
1624 * Create a RepoAuthType for a Type.
1626 * RepoAuthTypes may contain things like RepoAuthType::Array*'s or
1627 * SStrings for class names. The emit code needs to handle making
1628 * sure these things are merged into the appropriate unit or repo.
1630 * Pre: !t.couldBe(BCls)
1631 * !t.subtypeOf(BBottom)
1633 RepoAuthType
make_repo_type(ArrayTypeTable::Builder
&, const Type
& t
);
1636 * Returns true iff an IsType testing for testTy/testOp on valTy might raise.
1638 bool is_type_might_raise(const Type
& testTy
, const Type
& valTy
);
1639 bool is_type_might_raise(IsTypeOp testOp
, const Type
& valTy
);
1642 * Returns true iff a compare of two types might raise a HAC notice
1644 bool compare_might_raise(const Type
& t1
, const Type
& t2
);
1647 * Given a type, adjust the type for the given type-constraint. If there's no
1648 * type-constraint, or if property type-hints aren't being enforced, then return
1649 * the type as is. This might return TBottom if the type is not compatible with
1652 Type
adjust_type_for_prop(const Index
& index
,
1653 const php::Class
& propCls
,
1654 const TypeConstraint
* tc
,
1657 //////////////////////////////////////////////////////////////////////