Use shape values at runtime for position data
[hiphop-php.git] / hphp / hhbbc / index.h
blob20df1bd33c3473c3224fa1154eabf279ac18b282
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 #pragma once
18 #include <memory>
19 #include <tuple>
20 #include <vector>
21 #include <map>
22 #include <exception>
24 #include <boost/variant.hpp>
25 #include <tbb/concurrent_hash_map.h>
27 #include <folly/synchronization/Baton.h>
28 #include <folly/Optional.h>
29 #include <folly/Hash.h>
31 #include "hphp/util/compact-vector.h"
32 #include "hphp/util/either.h"
33 #include "hphp/util/tribool.h"
35 #include "hphp/runtime/base/repo-auth-type-array.h"
36 #include "hphp/runtime/vm/type-constraint.h"
38 #include "hphp/hhbbc/misc.h"
40 namespace HPHP { namespace HHBBC {
42 //////////////////////////////////////////////////////////////////////
44 struct Type;
45 struct Index;
46 struct PublicSPropMutations;
47 struct FuncAnalysisResult;
48 struct Context;
49 struct ContextHash;
50 struct CallContext;
51 struct PropertiesInfo;
53 extern const Type TCell;
55 namespace php {
56 struct Class;
57 struct Prop;
58 struct Record;
59 struct Const;
60 struct Func;
61 struct Unit;
62 struct Program;
65 //////////////////////////////////////////////////////////////////////
68 * This module contains functions for building and querying an Index
69 * of data relating to "resolved" versions of the names in of a
70 * php::Program. It also records dependencies so it is possible to
71 * tell which parts of the program may be interested in new inferred
72 * information about other parts of the program.
74 * The main entry point here is the Index class. The Index is built
75 * after parse time, and then analysis can query it for information.
78 //////////////////////////////////////////////////////////////////////
80 enum class Dep : uintptr_t {
81 /* This dependency should trigger when the return type changes */
82 ReturnTy = (1u << 0),
83 /* This dependency should trigger when a DefCns is resolved */
84 ConstVal = (1u << 1),
85 /* This dependency should trigger when a class constant is resolved */
86 ClsConst = (1u << 2),
87 /* This dependency should trigger when the bad initial prop value bit for a
88 * class changes */
89 PropBadInitialValues = (1u << 3),
90 /* This dependency should trigger when a public static property with a
91 * particular name changes */
92 PublicSPropName = (1u << 4),
93 /* This dependency means that we refused to do inline analysis on
94 * this function due to inline analysis depth. The dependency will
95 * trigger if the target function becomes effect-free, or gets a
96 * literal return value.
98 InlineDepthLimit = (1u << 5),
102 * A DependencyContext encodes enough of the context to record a dependency - a
103 * php::Func, if we're doing private property analysis and its a suitable class,
104 * a php::Class, or a public static property with a particular name.
107 enum class DependencyContextType : uint16_t {
108 Func,
109 Class,
110 PropName
113 using DependencyContext = CompactTaggedPtr<const void, DependencyContextType>;
115 struct DependencyContextLess {
116 bool operator()(const DependencyContext& a,
117 const DependencyContext& b) const {
118 return a.getOpaque() < b.getOpaque();
122 struct DependencyContextEquals {
123 bool operator()(const DependencyContext& a,
124 const DependencyContext& b) const {
125 return a.getOpaque() == b.getOpaque();
129 struct DependencyContextHash {
130 size_t operator()(const DependencyContext& d) const {
131 return pointer_hash<void>{}(reinterpret_cast<void*>(d.getOpaque()));
135 struct DependencyContextHashCompare : DependencyContextHash {
136 bool equal(const DependencyContext& a, const DependencyContext& b) const {
137 return a.getOpaque() == b.getOpaque();
139 size_t hash(const DependencyContext& d) const { return (*this)(d); }
142 using DependencyContextSet = hphp_hash_set<DependencyContext,
143 DependencyContextHash,
144 DependencyContextEquals>;
145 using ContextSet = hphp_hash_set<Context, ContextHash>;
147 std::string show(Context);
149 using ConstantMap = hphp_hash_map<SString, TypedValue>;
152 * State of properties on a class. Map from property name to its
153 * Type.
155 template <typename T = Type> // NB: The template param here is to
156 // break a cyclic dependency on Type.
157 struct PropStateElem {
158 T ty;
159 const TypeConstraint* tc = nullptr;
160 Attr attrs;
162 bool operator==(const PropStateElem<T>& o) const {
163 return ty == o.ty && tc == o.tc && attrs == o.attrs;
166 using PropState = std::map<LSString,PropStateElem<>>;
169 * The result of Index::lookup_static
171 template <typename T = Type> // NB: The template parameter is here to
172 // break a cyclic dependency on Type.
173 struct PropLookupResult {
174 T ty; // The best known type of the property (TBottom if not found)
175 SString name; // The statically known name of the string, if any
176 TriBool found; // If the property was found
177 TriBool isConst; // If the property is AttrConst
178 TriBool readOnly; // If the property is AttrIsReadOnly
179 TriBool lateInit; // If the property is AttrLateInit
180 bool classInitMightRaise; // If class initialization during the
181 // property access can raise (unlike the
182 // others, this is only no or maybe).
185 template <typename T>
186 inline PropLookupResult<T>& operator|=(PropLookupResult<T>& a,
187 const PropLookupResult<T>& b) {
188 assertx(a.name == b.name);
189 a.ty |= b.ty;
190 a.found |= b.found;
191 a.isConst |= b.isConst;
192 a.readOnly |= b.readOnly;
193 a.lateInit |= b.lateInit;
194 a.classInitMightRaise |= b.classInitMightRaise;
195 return a;
198 std::string show(const PropLookupResult<Type>&);
201 * The result of Index::merge_static_type
203 template <typename T = Type> // NB: The template parameter is here to
204 // break a cyclic dependency on Type
205 struct PropMergeResult {
206 T adjusted; // The merged type, potentially adjusted according to
207 // the prop's type-constraint (it's the subtype of the
208 // merged type that would succeed).
209 TriBool throws; // Whether the mutation this merge represents
210 // can throw.
213 template <typename T>
214 inline PropMergeResult<T>& operator|=(PropMergeResult<T>& a,
215 const PropMergeResult<T>& b) {
216 a.adjusted |= b.adjusted;
217 a.throws |= b.throws;
218 return a;
221 std::string show(const PropMergeResult<Type>&);
223 //////////////////////////////////////////////////////////////////////
225 // private types
226 struct ClassInfo;
227 struct RecordInfo;
229 //////////////////////////////////////////////////////////////////////
232 * References to "resolved" entities with information in the index are
233 * in the res:: namespace.
235 * These represent handles to program entities that may have variable
236 * amounts of information. For example, we may know the name of a
237 * class in a res::Class, but do not know for sure which php::Class
238 * struct is actually associated with it.
240 namespace res {
243 * A resolved runtime Class, for a particular php::Class.
245 * Provides various lookup tables that allow querying the Class'
246 * information.
248 struct Class {
250 * Returns whether two classes are definitely same at runtime. If
251 * this function returns false, they still *may* be the same at
252 * runtime.
254 bool same(const Class&) const;
257 * Returns true if this class is definitely going to be a subtype
258 * of `o' at runtime. If this function returns false, this may
259 * still be a subtype of `o' at runtime, it just may not be known.
260 * A typical example is with "non unique" classes.
262 bool mustBeSubtypeOf(const Class& o) const;
265 * Returns false if this class is definitely not going to be a subtype
266 * of `o' at runtime. If this function returns true, this may
267 * still not be a subtype of `o' at runtime, it just may not be known.
268 * A typical example is with "non unique" classes.
270 bool maybeSubtypeOf(const Class& o) const;
273 * If this function return false, it is known that this class
274 * is in no subtype relationship with the argument Class 'o'.
275 * Returns true if this class could be a subtype of `o' at runtime.
276 * When true is returned the two classes may still be unrelated but it is
277 * not possible to tell. A typical example is with "non unique" classes.
279 bool couldBe(const Class& o) const;
282 * Returns the name of this class. Non-null guarantee.
284 SString name() const;
287 * Whether this class could possibly be an interface/interface or trait.
289 * True means it might be, false means it is not.
291 bool couldBeInterface() const;
294 * Whether this class must be an interface.
296 * True means it is, false means it might not be.
298 bool mustBeInterface() const;
300 * Returns whether this type has the no override attribute, that is, if it
301 * is a final class (explicitly marked by the user or known by the static
302 * analysis).
304 * When returning false the class is guaranteed to be final. When returning
305 * true the system cannot tell though the class may still be final.
307 bool couldBeOverriden() const;
310 * Whether this class (or its subtypes) could possibly have have
311 * a magic toBoolean() method.
313 bool couldHaveMagicBool() const;
316 * Whether this class could possibly have a derived class that is mocked.
317 * Including itself.
319 bool couldHaveMockedDerivedClass() const;
322 * Whether this class could possibly be mocked.
324 bool couldBeMocked() const;
327 * Whether this class could have reified generics
329 bool couldHaveReifiedGenerics() const;
332 * Returns whether this resolved class might distinguish being constructed
333 * dynamically versus being constructed normally (IE, might raise a notice).
335 bool mightCareAboutDynConstructs() const;
338 * Whether this class (or clases derived from it) could have const props.
340 bool couldHaveConstProp() const;
341 bool derivedCouldHaveConstProp() const;
344 * Returns the Class that is the first common ancestor between 'this' and 'o'.
345 * If there is no common ancestor folly::none is returned
347 folly::Optional<Class> commonAncestor(const Class& o) const;
350 * Returns the res::Class for this Class's parent if there is one,
351 * or nullptr.
353 folly::Optional<Class> parent() const;
356 * Returns true if we have a ClassInfo for this Class.
358 bool resolved() const {
359 return val.right() != nullptr;
363 * Returns the php::Class for this Class if there is one, or
364 * nullptr.
366 const php::Class* cls() const;
368 private:
369 explicit Class(Either<SString,ClassInfo*>);
370 template <bool> bool subtypeOfImpl(const Class&) const;
372 private:
373 friend std::string show(const Class&);
374 friend struct ::HPHP::HHBBC::Index;
375 friend struct ::HPHP::HHBBC::PublicSPropMutations;
376 Either<SString,ClassInfo*> val;
380 * A resolved runtime Record, for a particular php::Record.
382 * Provides various lookup tables that allow querying the Record's
383 * information.
385 struct Record {
387 * Returns whether two records are definitely same at runtime. If
388 * this function returns false, they still *may* be the same at
389 * runtime.
391 bool same(const Record&) const;
394 * Returns true if this record is definitely going to be a subtype
395 * of `o' at runtime. If this function returns false, this may
396 * still be a subtype of `o' at runtime, it just may not be known.
397 * A typical example is with "non unique" records.
399 bool mustBeSubtypeOf(const Record& o) const;
402 * Returns false if this record is definitely not going to be a subtype
403 * of `o' at runtime. If this function returns true, this may
404 * still not be a subtype of `o' at runtime, it just may not be known.
406 bool maybeSubtypeOf(const Record& o) const;
409 * If this function return false, it is known that this record
410 * is in no subtype relationship with the argument record 'o'.
411 * Returns true if this record could be a subtype of `o' at runtime.
412 * When true is returned the two records may still be unrelated but it is
413 * not possible to tell. A typical example is with "non unique" records.
415 bool couldBe(const Record& o) const;
418 * Returns false if this is a final record.
420 bool couldBeOverriden() const;
423 * Returns the name of this record. Non-null guarantee.
425 SString name() const;
428 * Returns the res::Record for this Record's parent if there is one,
429 * or nullptr.
431 folly::Optional<Record> parent() const;
434 * Returns the Record that is the first common ancestor between
435 * 'this' and 'o'.
436 * If there is no common ancestor folly::none is returned
438 folly::Optional<Record> commonAncestor(const Record&) const;
441 * Returns true if we have a RecordInfo for this Record.
443 bool resolved() const {
444 return val.right() != nullptr;
448 * Returns the php::Record for this Record if there is one, or
449 * nullptr.
451 const php::Record* rec() const;
453 private:
454 explicit Record(Either<SString,RecordInfo*>);
455 template <bool> bool subtypeOfImpl(const Record&) const;
457 private:
458 friend std::string show(const Record&);
459 friend struct ::HPHP::HHBBC::Index;
460 Either<SString,RecordInfo*> val;
464 * This is an abstraction layer to represent possible runtime function
465 * resolutions.
467 * Internally, this may only know the name of the function (or method), or we
468 * may know exactly which source-code-level function it refers to, or we may
469 * only have ruled it down to one of a few functions in a class hierarchy. The
470 * interpreter can treat all these cases the same way using this.
472 struct Func {
474 * Returns the name of this function. Non-null guarantee.
476 SString name() const;
479 * If this resolved function represents exactly one php::Func, return it.
481 const php::Func* exactFunc() const;
484 * Returns whether this resolved function is definitely safe to constant fold.
486 bool isFoldable() const;
489 * Whether this function could have reified generics
491 bool couldHaveReifiedGenerics() const;
494 * Returns whether this resolved function might distinguish being called
495 * dynamically versus being called normally (IE, might raise a notice).
497 bool mightCareAboutDynCalls() const;
500 * Returns whether this resolved function might be a builtin.
502 bool mightBeBuiltin() const;
505 * Minimum/maximum bound on the number of non-variadic parameters of the
506 * function.
508 uint32_t minNonVariadicParams() const;
509 uint32_t maxNonVariadicParams() const;
511 struct FuncInfo;
512 struct MethTabEntryPair;
513 struct FuncFamily;
515 private:
516 friend struct ::HPHP::HHBBC::Index;
517 struct FuncName {
518 FuncName(SString n, bool r) : name{n}, renamable{r} {}
519 bool operator==(FuncName o) const { return name == o.name; }
520 SString name;
521 bool renamable;
523 struct MethodName {
524 bool operator==(MethodName o) const { return name == o.name; }
525 SString name;
527 using Rep = boost::variant< FuncName
528 , MethodName
529 , FuncInfo*
530 , const MethTabEntryPair*
531 , FuncFamily*
534 private:
535 Func(const Index*, Rep);
536 friend std::string show(const Func&);
538 private:
539 const Index* index;
540 Rep val;
544 * Produce a trace-able string for a res::Func or res::Class.
546 std::string show(const Func&);
547 std::string show(const Class&);
551 //////////////////////////////////////////////////////////////////////
554 * This class encapsulates the known facts about the program, with a
555 * whole-program view.
557 * This structure contains unowned pointers into the php::Program it
558 * was created for. It should not out-live the Program.
560 * The const member functions of this class are thread safe for
561 * concurrent reads and writes. The non-const functions should be
562 * called in a single threaded context only (they are used during the
563 * "update" step in between whole program analysis rounds).
565 struct Index {
567 struct NonUniqueSymbolException : std::exception {
568 explicit NonUniqueSymbolException(std::string msg) : msg(msg) {}
569 const char* what() const noexcept override { return msg.c_str(); }
570 private:
571 std::string msg;
575 * Create an Index for a php::Program. Performs some initial
576 * analysis of the program.
578 explicit Index(php::Program*);
581 * This class must not be destructed after its associated
582 * php::Program.
584 ~Index();
587 * The index operates in two modes: frozen, and unfrozen.
589 * Conceptually, the index is mutable and may acquire new
590 * information until it has been frozen, and once frozen, it retains
591 * the information it had at the point it was frozen.
593 * The reason this exists is because certain functions on the index
594 * may cause it to need to consult information in the bodies of
595 * functions other than the Context passed in. Specifically, if the
596 * interpreter tries to look up the return type for a callee in a
597 * given CallContext, the index may choose to recursively invoke
598 * type inference on that callee's function body to see if more
599 * precise information can be determined, unless it is frozen.
601 * This is fine until the final pass, because all bytecode is
602 * read-only at that stage. However, in the final pass, other
603 * threads might be optimizing a callee's bytecode and changing it,
604 * so we should not be reading from it to perform type inference
605 * concurrently. Freezing the index tells it it can't do that
606 * anymore.
608 * These are the functions to query and transition to frozen state.
610 bool frozen() const;
611 void freeze();
612 void thaw();
615 * Throw away data structures that won't be needed during or after
616 * the final pass. Currently the dependency map, which can take a
617 * long time to destroy.
619 void cleanup_for_final();
622 * Throw away data structures that won't be needed after the emit
623 * stage.
625 void cleanup_post_emit();
628 * The Index contains a Builder for an ArrayTypeTable.
630 * If we're creating assert types with options.InsertAssertions, we
631 * need to keep track of which array types exist in the whole
632 * program in order to include it in the repo.
634 std::unique_ptr<ArrayTypeTable::Builder>& array_table_builder() const;
637 * Try to resolve which record will be the record named `name`,
638 * if we can resolve it to a single record.
640 * Note, the returned record may or may not be *defined* at the
641 * program point you care about (it could be non-hoistable, even
642 * though it's unique, for example).
644 * Returns folly::none if we can't prove the supplied name must be a
645 * record type. (E.g. if there are type aliases.)
647 folly::Optional<res::Record> resolve_record(SString name) const;
650 * Find all the closures created inside the context of a given
651 * php::Class.
653 const CompactVector<const php::Class*>*
654 lookup_closures(const php::Class*) const;
657 * Find all the extra methods associated with a class from its
658 * traits.
660 const hphp_fast_set<const php::Func*>*
661 lookup_extra_methods(const php::Class*) const;
664 * Try to find a res::Class for a given php::Class.
666 * Note, the returned class may or may not be *defined* at the
667 * program point you care about (it could be non-hoistable, even
668 * though it's unique, for example).
670 * Returns a name-only resolution if there are no legal
671 * instantiations of the class, or if there is more than one.
673 res::Class resolve_class(const php::Class*) const;
676 * Try to resolve which class will be the class named `name' from a
677 * given context, if we can resolve it to a single class.
679 * Note, the returned class may or may not be *defined* at the
680 * program point you care about (it could be non-hoistable, even
681 * though it's unique, for example).
683 * Returns folly::none if we can't prove the supplied name must be a
684 * object type. (E.g. if there are type aliases.)
686 folly::Optional<res::Class> resolve_class(Context, SString name) const;
689 * Try to resolve self/parent types for the given context
691 folly::Optional<res::Class> selfCls(const Context& ctx) const;
692 folly::Optional<res::Class> parentCls(const Context& ctx) const;
694 template <typename T>
695 struct ResolvedInfo {
696 AnnotType type;
697 bool nullable;
698 T value;
702 * Try to resolve name, looking through TypeAliases and enums.
704 ResolvedInfo<boost::variant<boost::blank,res::Class,res::Record>>
705 resolve_type_name(SString name) const;
708 * Resolve a closure class.
710 * Returns both a resolved Class, and the actual php::Class for the
711 * closure.
713 std::pair<res::Class,php::Class*>
714 resolve_closure_class(Context ctx, int32_t idx) const;
717 * Return a resolved class for a builtin class.
719 * Pre: `name' must be the name of a class defined in a systemlib.
721 res::Class builtin_class(SString name) const;
724 * Try to resolve a function named `name' from a given context.
726 * Note, the returned function may or may not be defined at the
727 * program point (it could require a function autoload that might
728 * fail).
730 res::Func resolve_func(Context, SString name) const;
733 * Try to resolve a class method named `name' with a given Context
734 * and class type.
736 * Pre: clsType.subtypeOf(BCls)
738 res::Func resolve_method(Context, Type clsType, SString name) const;
741 * Try to resolve a class constructor for the supplied class type.
743 * Returns: folly::none if it can't at least figure out a func
744 * family for the call.
746 folly::Optional<res::Func>
747 resolve_ctor(Context, res::Class rcls, bool exact) const;
750 * Give the Type in our type system that matches an hhvm
751 * TypeConstraint, subject to the information in this Index.
753 * This function returns a subtype of Cell, although TypeConstraints
754 * at runtime can match reference parameters. The caller should
755 * make sure to handle that case.
757 * For soft constraints (@), this function returns Cell.
759 * For some non-soft constraints (such as "Stringish"), this
760 * function may return a Type that is a strict supertype of the
761 * constraint's type.
763 * If something is known about the type of the object against which
764 * the constraint will be checked, it can be passed in to help
765 * disambiguate certain constraints (useful because we don't support
766 * arbitrary unions, or intersection).
768 Type lookup_constraint(Context, const TypeConstraint&,
769 const Type& t = TCell) const;
772 * If this function returns true, it is safe to assume that Type t
773 * will always satisfy TypeConstraint tc at run time.
775 bool satisfies_constraint(Context, const Type& t,
776 const TypeConstraint& tc) const;
779 * Returns true if the given type-hint (declared on the given class) might not
780 * be enforced at runtime (IE, it might map to mixed or be soft).
782 bool prop_tc_maybe_unenforced(const php::Class& propCls,
783 const TypeConstraint& tc) const;
786 * Returns true if the type constraint can contain a reified type
787 * Currently, only classes and interfaces are supported
789 bool could_have_reified_type(Context ctx, const TypeConstraint& tc) const;
792 * Lookup what the best known Type for a class constant would be,
793 * using a given Index and Context, if a class of that name were
794 * loaded.
795 * If allow_tconst is not set, type constants will not be returned.
796 * lookup_class_const_ptr version returns the statically known version
797 * of the const if it can find it, otherwise returns nullptr.
799 Type lookup_class_constant(Context, res::Class, SString cns,
800 bool allow_tconst) const;
801 const php::Const* lookup_class_const_ptr(Context, res::Class, SString cns,
802 bool allow_tconst) const;
805 * Lookup what the best known Type for a constant would be, using a
806 * given Index and Context, if a constant of that name were defined.
808 Type lookup_constant(Context ctx, SString cnsName) const;
811 * Return true if the return value of the function might depend on arg.
813 bool func_depends_on_arg(const php::Func* func, int arg) const;
816 * If func is effect-free when called with args, and it returns a constant,
817 * return that constant; otherwise return TInitCell.
819 Type lookup_foldable_return_type(Context ctx,
820 const php::Func* func,
821 Type ctxType,
822 CompactVector<Type> args) const;
824 * Return the best known return type for a resolved function, in a
825 * context insensitive way. Returns TInitCell at worst.
827 Type lookup_return_type(Context, res::Func, Dep dep = Dep::ReturnTy) const;
830 * Return the best known return type for a resolved function, given
831 * the supplied calling context. Returns TInitCell at worst.
833 * During analyze phases, this function may re-enter analyze in
834 * order to interpret the callee with these argument types.
836 Type lookup_return_type(Context caller,
837 const CompactVector<Type>& args,
838 const Type& context,
839 res::Func,
840 Dep dep = Dep::ReturnTy) const;
843 * Look up the return type for an unresolved function. The
844 * interpreter should not use this routine---it's for stats or debug
845 * dumps.
847 * Nothing may be writing to the index when this function is used,
848 * but concurrent readers are allowed.
850 Type lookup_return_type_raw(const php::Func*) const;
853 * Return the best known types of a closure's used variables (on
854 * entry to the closure). The function is the closure body.
856 * If move is true, the value will be moved out of the index. This
857 * should only be done at emit time. (note that the only other user
858 * of this info is analysis, which only uses it when processing the
859 * owning class, so its safe to kill after emitting the owning
860 * unit).
862 CompactVector<Type>
863 lookup_closure_use_vars(const php::Func*,
864 bool move = false) const;
867 * Return the availability of $this on entry to the provided method.
868 * If the Func provided is not a method of a class false is
869 * returned.
871 bool lookup_this_available(const php::Func*) const;
874 * Returns the parameter preparation kind (if known) for parameter
875 * `paramId' on the given resolved Func.
877 PrepKind lookup_param_prep(Context, res::Func, uint32_t paramId) const;
880 * Returns the number of inout parameters expected by func (if known).
882 folly::Optional<uint32_t> lookup_num_inout_params(Context, res::Func) const;
885 * Returns the control-flow insensitive inferred private instance
886 * property types for a Class. The Class doesn't need to be
887 * resolved, because private properties don't depend on the
888 * inheritance hierarchy.
890 * The Index tracks the largest types for private properties that
891 * are guaranteed to hold at any program point.
893 * If move is true, the value will be moved out of the index. This
894 * should only be done at emit time. (note that the only other user
895 * of this info is analysis, which only uses it when processing the
896 * owning class, so its safe to kill after emitting the owning
897 * unit).
899 PropState lookup_private_props(const php::Class*,
900 bool move = false) const;
903 * Returns the control-flow insensitive inferred private static
904 * property types for a Class. The class doesn't need to be
905 * resolved for the same reasons as for instance properties.
907 * The Index tracks the largest types for private static properties
908 * that are guaranteed to hold at any program point.
910 * If move is true, the value will be moved out of the index. This
911 * should only be done at emit time. (note that the only other user
912 * of this info is analysis, which only uses it when processing the
913 * owning class, so its safe to kill after emitting the owning
914 * unit).
916 PropState lookup_private_statics(const php::Class*,
917 bool move = false) const;
918 PropState lookup_public_statics(const php::Class*) const;
921 * Lookup metadata about the static property access `cls'::`name',
922 * in the current context `ctx'. The returned metadata not only
923 * includes the best known type of the property, but whether it is
924 * definitely found, and whether the access might raise for various
925 * reasons. This function is responsible for walking the class
926 * hierarchy to find the appropriate property while applying
927 * accessibility rules. This is intended to be the source of truth
928 * about static properties during analysis.
930 PropLookupResult<> lookup_static(Context ctx,
931 const PropertiesInfo& privateProps,
932 const Type& cls,
933 const Type& name) const;
936 * Lookup if initializing (which is a side-effect of several bytecodes) the
937 * given class might raise.
939 bool lookup_class_init_might_raise(Context, res::Class) const;
942 * Lookup the best known type for a public (non-static) property. Since we
943 * don't do analysis on public properties, this just inferred from the
944 * property's type-hint (if enforced).
946 Type lookup_public_prop(const Type& cls, const Type& name) const;
947 Type lookup_public_prop(const php::Class* cls, SString name) const;
950 * We compute the interface vtables in a separate thread. It needs
951 * to be joined (in single threaded context) before calling
952 * lookup_iface_vtable_slot.
954 void join_iface_vtable_thread() const;
957 * Returns the computed vtable slot for the given class, if it's an interface
958 * that was given a vtable slot. No two interfaces implemented by the same
959 * class will share the same vtable slot. May return kInvalidSlot, if the
960 * given class isn't an interface or if it wasn't assigned a slot.
962 Slot lookup_iface_vtable_slot(const php::Class*) const;
965 * Return the DependencyContext for ctx.
967 DependencyContext dependency_context(const Context& ctx) const;
970 * Determine whether to use class-at-a-time, or function-at-a-time
971 * dependencies.
973 * Must be called in single-threaded context.
975 void use_class_dependencies(bool f);
978 * Merge the type `val' into the known type for static property
979 * `cls'::`name'. Depending on what we know about `cls' and `name',
980 * this might affect multiple properties. This function is
981 * responsible for walking the class hierarchy to find the
982 * appropriate property while applying accessibility
983 * rules. Mutations of AttrConst properties are ignored unless
984 * `ignoreConst' is set to true. If `checkUB' is true, upper-bound
985 * type constraints are consulted in addition to the normal type
986 * constraints.
988 * The result tells you the subtype of val that would be
989 * successfully set (according to the type constraints), and if the
990 * mutation would throw or not.
992 PropMergeResult<> merge_static_type(Context ctx,
993 PublicSPropMutations& publicMutations,
994 PropertiesInfo& privateProps,
995 const Type& cls,
996 const Type& name,
997 const Type& val,
998 bool checkUB = false,
999 bool ignoreConst = false,
1000 bool mustBeReadOnly = false) const;
1003 * Initialize the initial types for public static properties. This should be
1004 * done after rewriting initial property values, as that affects the types.
1006 void init_public_static_prop_types();
1009 * Refine the types of the class constants defined by an 86cinit,
1010 * based on a round of analysis.
1012 * No other threads should be using ctx.cls->constants or deps when
1013 * this function is called.
1015 * Merges the set of Contexts that depended on the constants defined
1016 * by this 86cinit.
1018 void refine_class_constants(
1019 const Context& ctx,
1020 const CompactVector<std::pair<size_t, TypedValue>>& resolved,
1021 DependencyContextSet& deps);
1024 * Refine the types of the constants defined by a function, based on
1025 * a round of analysis.
1027 * Constants not defined by a pseudomain are considered unknowable
1029 * No other threads should be calling functions on this Index when
1030 * this function is called.
1032 * Merges the set of Contexts that depended on the constants defined
1033 * by this php::Func into deps.
1035 void refine_constants(const FuncAnalysisResult& fa,
1036 DependencyContextSet& deps);
1039 * Refine the return type for a function, based on a round of
1040 * analysis.
1042 * No other threads should be calling functions on this Index when
1043 * this function is called.
1045 * Merges the set of Contexts that depended on the return type of
1046 * this php::Func into deps.
1048 void refine_return_info(const FuncAnalysisResult& fa,
1049 DependencyContextSet& deps);
1052 * Refine the used var types for a closure, based on a round of
1053 * analysis.
1055 * No other threads should be calling functions on this Index when
1056 * this function is called.
1058 * Returns: true if the types have changed.
1060 bool refine_closure_use_vars(const php::Class*,
1061 const CompactVector<Type>&);
1064 * Refine the private property types for a class, based on a round
1065 * of analysis.
1067 * No other threads should be calling functions on this Index when
1068 * this function is called.
1070 void refine_private_props(const php::Class* cls,
1071 const PropState&);
1074 * Refine the static private property types for a class, based on a
1075 * round of analysis.
1077 * No other threads should be calling functions on this Index when
1078 * this function is called.
1080 void refine_private_statics(const php::Class* cls,
1081 const PropState&);
1084 * Record in the index that the given set of public static property mutations
1085 * has been found while analyzing the given function. During a round of
1086 * analysis, the mutations are gathered from the analysis results for each
1087 * function, recorded in the index, and then refine_public_statics is called
1088 * to process the mutations and update the index.
1090 * No other threads should be calling functions on this Index when this
1091 * function is called.
1093 void record_public_static_mutations(const php::Func& func,
1094 PublicSPropMutations mutations);
1098 * If we resolve the intial value of a public property, we need to
1099 * tell the refine_public_statics phase about it, because the init
1100 * value won't be included in the mutations any more.
1102 * Note that we can't modify the initial value here, because other
1103 * threads might be reading it (via loookup_public_static), so we
1104 * set a flag to tell us to update it during the next
1105 * refine_public_statics pass.
1107 void update_static_prop_init_val(const php::Class* cls,
1108 SString name) const;
1110 * After a round of analysis with all the public static property mutations
1111 * being recorded with record_public_static_mutations, the types can be
1112 * reflected into the index for use during another type inference pass.
1114 * No other threads should be calling functions on this Index when this
1115 * function is called.
1117 * Merges the set of Contexts that depended on a public static property whose
1118 * type has changed.
1120 void refine_public_statics(DependencyContextSet& deps);
1123 * Refine whether the given class has properties with initial values which
1124 * might violate their type-hints.
1126 * No other threads should be calling functions on this Index when this
1127 * function is called.
1129 void refine_bad_initial_prop_values(const php::Class* cls,
1130 bool value,
1131 DependencyContextSet& deps);
1134 * Mark any properties in cls that definitely do not redeclare a property in
1135 * the parent, which has an inequivalent type-hint.
1137 void mark_no_bad_redeclare_props(php::Class& cls) const;
1140 * Rewrite the initial values of any AttrSystemInitialValue properties to
1141 * something more suitable for its type-hint, and add AttrNoImplicitNullable
1142 * where appropriate.
1144 * This must be done before any analysis is done, as the initial values
1145 * affects the analysis.
1147 void rewrite_default_initial_values(php::Program&) const;
1150 * Return true if the resolved function supports async eager return.
1152 folly::Optional<bool> supports_async_eager_return(res::Func rfunc) const;
1155 * Return true if the function is effect free.
1157 bool is_effect_free(res::Func rfunc) const;
1158 bool is_effect_free(const php::Func* func) const;
1161 * Do any necessary fixups to a return type.
1163 * Note that eg for an async function it will map Type to
1164 * WaitH<Type>.
1166 void fixup_return_type(const php::Func*, Type&) const;
1169 * Return true if we know for sure that one php::Class must derive
1170 * from another at runtime, in all possible instantiations.
1172 bool must_be_derived_from(const php::Class*,
1173 const php::Class*) const;
1175 struct IndexData;
1176 private:
1177 Index(const Index&) = delete;
1178 Index& operator=(Index&&) = delete;
1180 private:
1181 friend struct PublicSPropMutations;
1183 res::Func resolve_func_helper(const php::Func*, SString) const;
1184 res::Func do_resolve(const php::Func*) const;
1185 bool could_be_related(const php::Class*,
1186 const php::Class*) const;
1188 template<bool getSuperType>
1189 Type get_type_for_constraint(Context,
1190 const TypeConstraint&,
1191 const Type&) const;
1193 struct ConstraintResolution;
1196 * Try to resolve name in the given context. Follows TypeAliases.
1198 ConstraintResolution resolve_named_type(
1199 const Context& ctx, SString name, const Type& candidate) const;
1201 ConstraintResolution get_type_for_annotated_type(
1202 Context ctx, AnnotType annot, bool nullable,
1203 SString name, const Type& candidate) const;
1205 void init_return_type(const php::Func* func);
1207 ResolvedInfo<boost::variant<boost::blank,SString,ClassInfo*,RecordInfo*>>
1208 resolve_type_name_internal(SString name) const;
1210 template<typename T>
1211 folly::Optional<T> resolve_type_impl(SString name) const;
1213 private:
1214 std::unique_ptr<IndexData> const m_data;
1217 //////////////////////////////////////////////////////////////////////
1220 * Used for collecting all mutations of public static property types.
1222 struct PublicSPropMutations {
1223 private:
1224 friend struct Index;
1226 struct KnownKey {
1227 bool operator<(KnownKey o) const {
1228 if (cinfo != o.cinfo) return cinfo < o.cinfo;
1229 return prop < o.prop;
1232 ClassInfo* cinfo;
1233 SString prop;
1236 using UnknownMap = std::map<SString,Type>;
1237 using KnownMap = std::map<KnownKey,Type>;
1239 // Public static property mutations are actually rare, so defer allocating the
1240 // maps until we actually see one.
1241 struct Data {
1242 bool m_nothing_known{false};
1243 UnknownMap m_unknown;
1244 KnownMap m_known;
1246 std::unique_ptr<Data> m_data;
1248 Data& get();
1250 void mergeKnown(const ClassInfo* ci, const php::Prop& prop, const Type& val);
1251 void mergeUnknownClass(SString prop, const Type& val);
1252 void mergeUnknown(Context);
1255 //////////////////////////////////////////////////////////////////////