take &self
[hiphop-php.git] / hphp / hhbbc / type-system.h
blob0a01e105b45cb48e52aa5a9ccd6e869e40a6aeb0
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
16 #ifndef incl_HHBBC_TYPE_SYSTEM_H_
17 #define incl_HHBBC_TYPE_SYSTEM_H_
19 #include <cstdint>
20 #include <vector>
21 #include <utility>
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 {
38 struct Type;
40 //////////////////////////////////////////////////////////////////////
43 * Type system.
45 * Here's an unmaintainable ascii-art diagram:
47 * Top
48 * |
49 * +-----+
50 * | | InitCell := Cell - Uninit
51 * Cls | ?X := X + InitNull
52 * | |
53 * Cls<=c Cell
54 * | |
55 * Cls=c +-------------+--------+-------+-------+-----+
56 * | | | | | |
57 * Unc | | Obj Res Record
58 * | \ | | / \
59 * | \ | | Obj<=c Obj<=WaitHandle
60 * Prim \ | | | |
61 * / | InitUnc | | Obj=c WaitH<T>
62 * / | / | | | |
63 * / | / | | | |
64 * / | / | | | |
65 * / |/ | | | |
66 * Null InitPrim | | | |
67 * / | / | | | Arr Str
68 * / | / | | | / \ / \
69 * Uninit InitNull | | SArr ... / CStr
70 * | | | /
71 * | | ... /
72 * | | /
73 * | \ /
74 * | \ /
75 * | \ /
76 * | \ /
77 * | SStr
78 * | |
79 * | SStr=s
80 * |
81 * +----------+
82 * | |
83 * Bool Num
84 * / \ | \
85 * True False Int Dbl
86 * | |
87 * Int=n Dbl=n
89 * Some notes on some of the basic types:
91 * {Init,}Prim
93 * "Primitive" types---these can be represented in a TypedValue without a
94 * pointer to the heap.
96 * {Init,}Unc
98 * "Uncounted" types---values of these types don't require reference
99 * counting.
101 * WaitH<T>
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.
106 * Array types:
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:
114 * Arr
116 * +----+--+--+---+
117 * | | | |
118 * | SArr CArr |
119 * | | | |
120 * +-------+---------------+
121 * | | | | |
122 * | ArrN +-----+ ArrE |
123 * | / \ | | / \ |
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
142 * of SArr.
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:
149 * SArrN(Bool,Int)
151 * Tuple-like static two-element array, with integer keys 0 and 1,
152 * containing a Bool and an Int with unknown values.
154 * Arr(Int,Dbl)
156 * An array of unknown countedness that is either empty, or a
157 * tuple-like array with two elements of types Int and Dbl.
159 * CArrN([Bool])
161 * Non-empty reference counted array with contiguous zero-based integer
162 * keys, unknown size, values all are subtypes of Bool.
164 * ArrN(x:Int,y:Int)
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
178 * with string keys.
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 {
197 BBottom = 0,
199 BUninit = 1ULL << 0,
200 BInitNull = 1ULL << 1,
201 BFalse = 1ULL << 2,
202 BTrue = 1ULL << 3,
203 BInt = 1ULL << 4,
204 BDbl = 1ULL << 5,
205 BSStr = 1ULL << 6, // static string
206 BCStr = 1ULL << 7, // counted string
207 BFunc = 1ULL << 8,
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
226 BObj = 1ULL << 22,
227 BRes = 1ULL << 23,
228 BCls = 1ULL << 24,
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,
270 BNum = BInt | BDbl,
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,
293 // Nullable types.
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) {
413 a = a & b;
414 return a;
417 constexpr const trep& operator|=(trep&a, trep b) {
418 a = a | b;
419 return a;
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;
429 #define DATATAGS \
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 {
443 None,
444 #define DT(name,...) name,
445 DATATAGS
446 #undef DT
449 //////////////////////////////////////////////////////////////////////
452 * Information about a class type. The class is either exact or a
453 * subtype of the supplied class.
455 struct DCls {
456 enum Tag : uint16_t { Exact, Sub };
458 DCls(Tag type, res::Class cls)
459 : type(type)
460 , cls(cls)
463 Tag type;
464 bool isCtx = false;
465 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.
475 struct DObj {
476 enum Tag : uint16_t { Exact, Sub };
478 DObj(Tag type, res::Class cls)
479 : type(type)
480 , cls(cls)
483 Tag type;
484 bool isCtx = false;
485 res::Class cls;
486 copy_ptr<Type> whType;
489 struct DArrLikePacked;
490 struct DArrLikePackedN;
491 struct DArrLikeMap;
492 struct DArrLikeMapN;
493 using MapElems = ArrayLikeMap<Cell>;
494 struct ArrKey;
495 struct IterTypes;
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
504 * static arrays.
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:
515 * top (folly::none)
516 * ____/|\___________
517 * / | \
518 * t_1 t_2 ... t_n (specific arrprov::Tag's)
519 * \____ | ___________/
520 * \|/
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 {
529 Empty,
530 NonEmpty,
531 Maybe
534 enum class ThrowMode {
535 None,
536 MaybeMissingElement,
537 MaybeBadKey,
538 MissingElement,
539 BadOperation,
542 //////////////////////////////////////////////////////////////////////
544 struct Type {
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;
556 ~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); }
563 size_t hash() const;
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
574 * context.
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}),
590 * but cheaper).
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; }
631 struct ArrayCat {
632 enum { None, Empty, Packed, Struct, Mixed } cat;
633 bool hasValue;
636 private:
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,
693 const ArrKey& key);
694 friend std::pair<Type,bool> arr_packedn_elem(const Type& pack,
695 const ArrKey& key);
696 friend std::pair<Type,ThrowMode> array_like_elem(const Type& arr,
697 const ArrKey& key,
698 const Type& defaultTy);
699 friend std::pair<Type,ThrowMode> array_like_set(Type arr,
700 const ArrKey& key,
701 const Type& val,
702 ProvTag src);
703 friend std::pair<Type,Type> array_like_newelem(Type arr, const Type& val,
704 ProvTag src);
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,
708 const Type& val,
709 ProvTag src);
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&,
716 const Type&);
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);
743 private:
744 union Data {
745 Data() {}
746 ~Data() {}
748 #define DT(tag_name,type,name) type name;
749 DATATAGS
750 #undef DT
753 template<class Ret, class T, class Function>
754 struct DDHelperFn;
756 private:
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;
774 private:
775 trep m_bits;
776 DataTag m_dataTag = DataTag::None;
777 Data m_data;
780 //////////////////////////////////////////////////////////////////////
782 struct ArrKey {
783 folly::Optional<int64_t> i;
784 folly::Optional<SString> s;
785 Type type;
786 bool mayThrow = false;
788 folly::Optional<Cell> tv() const {
789 assert(!i || !s);
790 if (i) {
791 return make_tv<KindOfInt64>(*i);
793 if (s) {
794 return make_tv<KindOfPersistentString>(*s);
796 return folly::none;
800 struct DArrLikePacked {
801 explicit DArrLikePacked(std::vector<Type> elems, ProvTag tag)
802 : elems(std::move(elems))
803 , provenance(tag)
806 std::vector<Type> elems;
807 ProvTag provenance;
810 struct DArrLikePackedN {
811 explicit DArrLikePackedN(Type t) : type(std::move(t)) {}
812 Type type;
815 struct DArrLikeMap {
816 DArrLikeMap() {}
817 explicit DArrLikeMap(MapElems map, ProvTag tag)
818 : map(std::move(map))
819 , provenance(tag)
821 MapElems map;
822 ProvTag provenance;
825 struct DArrLikeMapN {
826 explicit DArrLikeMapN(Type key, Type val)
827 : key(std::move(key))
828 , val(std::move(val))
830 Type key;
831 Type val;
834 //////////////////////////////////////////////////////////////////////
836 #define TYPES(X) \
837 X(Bottom) \
838 X(Uninit) \
839 X(InitNull) \
840 X(False) \
841 X(True) \
842 X(Int) \
843 X(Dbl) \
844 X(SStr) \
845 X(SArrE) \
846 X(SArrN) \
847 X(Obj) \
848 X(Res) \
849 X(Cls) \
850 X(Func) \
851 X(ClsMeth) \
852 X(Record) \
853 X(SVecE) \
854 X(SVecN) \
855 X(SDictE) \
856 X(SDictN) \
857 X(SKeysetE) \
858 X(SKeysetN) \
859 X(Null) \
860 X(Bool) \
861 X(Num) \
862 X(Str) \
863 X(SArr) \
864 X(ArrE) \
865 X(ArrN) \
866 X(Arr) \
867 X(SVec) \
868 X(VecE) \
869 X(VecN) \
870 X(Vec) \
871 X(SDict) \
872 X(DictE) \
873 X(DictN) \
874 X(Dict) \
875 X(SKeyset) \
876 X(KeysetE) \
877 X(KeysetN) \
878 X(Keyset) \
879 X(SPArrE) \
880 X(SPArrN) \
881 X(SPArr) \
882 X(PArrE) \
883 X(PArrN) \
884 X(PArr) \
885 X(SVArrE) \
886 X(SVArrN) \
887 X(SVArr) \
888 X(VArrE) \
889 X(VArrN) \
890 X(VArr) \
891 X(SDArrE) \
892 X(SDArrN) \
893 X(SDArr) \
894 X(DArrE) \
895 X(DArrN) \
896 X(DArr) \
897 X(UncArrKey) \
898 X(ArrKey) \
899 X(UncStrLike) \
900 X(StrLike) \
901 X(InitPrim) \
902 X(Prim) \
903 X(InitUnc) \
904 X(Unc) \
905 X(OptTrue) \
906 X(OptFalse) \
907 X(OptBool) \
908 X(OptInt) \
909 X(OptDbl) \
910 X(OptNum) \
911 X(OptSStr) \
912 X(OptStr) \
913 X(OptSArrE) \
914 X(OptSArrN) \
915 X(OptSArr) \
916 X(OptArrE) \
917 X(OptArrN) \
918 X(OptArr) \
919 X(OptObj) \
920 X(OptRes) \
921 X(OptFunc) \
922 X(OptCls) \
923 X(OptClsMeth) \
924 X(OptRecord) \
925 X(OptSVecE) \
926 X(OptSVecN) \
927 X(OptSVec) \
928 X(OptVecE) \
929 X(OptVecN) \
930 X(OptVec) \
931 X(OptSDictE) \
932 X(OptSDictN) \
933 X(OptSDict) \
934 X(OptDictE) \
935 X(OptDictN) \
936 X(OptDict) \
937 X(OptSKeysetE) \
938 X(OptSKeysetN) \
939 X(OptSKeyset) \
940 X(OptKeysetE) \
941 X(OptKeysetN) \
942 X(OptKeyset) \
943 X(OptSPArrE) \
944 X(OptSPArrN) \
945 X(OptSPArr) \
946 X(OptPArrE) \
947 X(OptPArrN) \
948 X(OptPArr) \
949 X(OptSVArrE) \
950 X(OptSVArrN) \
951 X(OptSVArr) \
952 X(OptVArrE) \
953 X(OptVArrN) \
954 X(OptVArr) \
955 X(OptSDArrE) \
956 X(OptSDArrN) \
957 X(OptSDArr) \
958 X(OptDArrE) \
959 X(OptDArrN) \
960 X(OptDArr) \
961 X(OptUncArrKey) \
962 X(OptArrKey) \
963 X(OptUncStrLike) \
964 X(OptStrLike) \
965 X(InitCell) \
966 X(Cell) \
967 X(Top)
969 #define X(y) extern const Type T##y;
970 TYPES(X)
971 #undef X
973 // These are treps that have B* names, but which are not "predefined"
974 // types. They are only allowed in combination with the corresponding
975 // S types.
976 #define NON_TYPES(X) \
977 X(CStr) \
978 X(CPArrE) \
979 X(CPArrN) \
980 X(CVArrE) \
981 X(CVArrN) \
982 X(CDArrE) \
983 X(CDArrN) \
984 X(CArrE) \
985 X(CArrN) \
986 X(CVecE) \
987 X(CVecN) \
988 X(CDictE) \
989 X(CDictN) \
990 X(CKeysetE) \
991 X(CKeysetN) \
992 X(CPArr) \
993 X(CVArr) \
994 X(CDArr) \
995 X(CArr) \
996 X(CVec) \
997 X(CDict) \
998 X(CKeyset) \
999 X(OptCStr) \
1000 X(OptCPArrE) \
1001 X(OptCPArrN) \
1002 X(OptCPArr) \
1003 X(OptCVArrE) \
1004 X(OptCVArrN) \
1005 X(OptCVArr) \
1006 X(OptCDArrE) \
1007 X(OptCDArrN) \
1008 X(OptCDArr) \
1009 X(OptCArrE) \
1010 X(OptCArrN) \
1011 X(OptCArr) \
1012 X(OptCVecE) \
1013 X(OptCVecN) \
1014 X(OptCVec) \
1015 X(OptCDictE) \
1016 X(OptCDictN) \
1017 X(OptCDict) \
1018 X(OptCKeysetE) \
1019 X(OptCKeysetN) \
1020 X(OptCKeyset)
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.
1039 Type sval(SString);
1040 Type ival(int64_t);
1041 Type dval(double);
1042 Type aval(SArray);
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.
1051 Type sempty();
1052 Type aempty();
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.
1062 Type some_aempty();
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.
1080 * Pre: !v.empty()
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.
1097 * Pre: !m.empty()
1099 Type arr_map(MapElems m);
1100 Type arr_map_darray(MapElems m);
1101 Type sarr_map(MapElems m);
1104 * Map-like arrays.
1106 Type arr_mapn(Type k, Type v);
1107 Type sarr_mapn(Type k, Type v);
1110 * vec types with known size.
1112 * Pre: !v.empty()
1114 Type vec(std::vector<Type> v, ProvTag);
1115 Type svec(std::vector<Type> v, ProvTag);
1118 * Vec type of unknown size.
1120 Type vec_n(Type);
1121 Type svec_n(Type);
1124 * Struct-like dicts.
1126 * Pre: !m.empty()
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.
1154 Type opt(Type t);
1157 * Return the non-optional version of the Type t.
1159 * Pre: is_opt(t)
1161 Type unopt(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
1195 * context.
1197 Type setctx(Type t, bool to = true);
1200 * This removes any context tags in the type `t`, even if nested inside other
1201 * types.
1203 Type unctx(Type t);
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&);
1218 template<
1219 typename Iterable,
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;
1229 return true;
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
1264 * provided object.
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
1307 * looked up.
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
1329 * IsTypeOp.
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
1398 * supplied types.
1400 Type intersection_of(Type a, Type b);
1403 * Make a type that represents values from either of the supplied
1404 * types.
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
1409 * finite steps.
1411 Type union_of(Type a, Type b);
1414 * Widening union.
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
1420 * point.
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
1428 * analyze.cpp.
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
1494 * type otherwise.
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
1507 * type otherwise.
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,
1577 ProvTag src);
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,
1581 const Type& val);
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
1601 * InitCell.
1603 struct IterTypes {
1604 Type key;
1605 Type value;
1606 // The number of elements we're iterating over:
1607 enum struct Count {
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
1614 Count count;
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
1618 // types.
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
1650 * the type-hint.
1652 Type adjust_type_for_prop(const Index& index,
1653 const php::Class& propCls,
1654 const TypeConstraint* tc,
1655 const Type& ty);
1657 //////////////////////////////////////////////////////////////////////
1661 #endif