fix hot shallow decls
[hiphop-php.git] / hphp / hhbbc / index.h
blob21b2102abd4d5bf7d5d8b632e889b3d7da26c90f
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/Hash.h>
30 #include "hphp/util/compact-vector.h"
31 #include "hphp/util/either.h"
32 #include "hphp/util/tribool.h"
34 #include "hphp/runtime/base/repo-auth-type-array.h"
35 #include "hphp/runtime/vm/type-constraint.h"
37 #include "hphp/hhbbc/hhbbc.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;
52 struct MethodsInfo;
54 struct TypeStructureResolution;
56 extern const Type TCell;
58 namespace php {
59 struct Class;
60 struct Prop;
61 struct Const;
62 struct Func;
63 struct Unit;
64 struct Program;
65 struct TypeAlias;
68 //////////////////////////////////////////////////////////////////////
71 * This module contains functions for building and querying an Index
72 * of data relating to "resolved" versions of the names in of a
73 * php::Program. It also records dependencies so it is possible to
74 * tell which parts of the program may be interested in new inferred
75 * information about other parts of the program.
77 * The main entry point here is the Index class. The Index is built
78 * after parse time, and then analysis can query it for information.
81 //////////////////////////////////////////////////////////////////////
83 enum class Dep : uintptr_t {
84 /* This dependency should trigger when the return type changes */
85 ReturnTy = (1u << 0),
86 /* This dependency should trigger when a DefCns is resolved */
87 ConstVal = (1u << 1),
88 /* This dependency should trigger when a class constant is resolved */
89 ClsConst = (1u << 2),
90 /* This dependency should trigger when the bad initial prop value bit for a
91 * class changes */
92 PropBadInitialValues = (1u << 3),
93 /* This dependency should trigger when a public static property changes */
94 PublicSProp = (1u << 4),
95 /* This dependency means that we refused to do inline analysis on
96 * this function due to inline analysis depth. The dependency will
97 * trigger if the target function becomes effect-free, or gets a
98 * literal return value.
100 InlineDepthLimit = (1u << 5),
104 * A DependencyContext encodes enough of the context to record a dependency - a
105 * php::Func, if we're doing private property analysis and its a suitable class,
106 * a php::Class, or a public static property.
109 enum class DependencyContextType : uint16_t {
110 Func,
111 Class,
112 Prop,
113 FuncFamily
116 using DependencyContext = CompactTaggedPtr<const void, DependencyContextType>;
118 struct DependencyContextLess {
119 bool operator()(const DependencyContext& a,
120 const DependencyContext& b) const {
121 return a.getOpaque() < b.getOpaque();
125 struct DependencyContextEquals {
126 bool operator()(const DependencyContext& a,
127 const DependencyContext& b) const {
128 return a.getOpaque() == b.getOpaque();
132 struct DependencyContextHash {
133 size_t operator()(const DependencyContext& d) const {
134 return pointer_hash<void>{}(reinterpret_cast<void*>(d.getOpaque()));
138 struct DependencyContextHashCompare : DependencyContextHash {
139 bool equal(const DependencyContext& a, const DependencyContext& b) const {
140 return a.getOpaque() == b.getOpaque();
142 size_t hash(const DependencyContext& d) const { return (*this)(d); }
145 using DependencyContextSet = hphp_hash_set<DependencyContext,
146 DependencyContextHash,
147 DependencyContextEquals>;
148 using ContextSet = hphp_hash_set<Context, ContextHash>;
150 std::string show(Context);
152 using ConstantMap = hphp_hash_map<SString, TypedValue>;
155 * State of properties on a class. Map from property name to its
156 * Type.
158 template <typename T = Type> // NB: The template param here is to
159 // break a cyclic dependency on Type.
160 struct PropStateElem {
161 T ty;
162 const TypeConstraint* tc = nullptr;
163 Attr attrs;
164 bool everModified;
166 bool operator==(const PropStateElem<T>& o) const {
167 return
168 ty == o.ty &&
169 tc == o.tc &&
170 attrs == o.attrs &&
171 everModified == o.everModified;
174 using PropState = std::map<LSString,PropStateElem<>>;
177 * The result of Index::lookup_static
179 template <typename T = Type> // NB: The template parameter is here to
180 // break a cyclic dependency on Type.
181 struct PropLookupResult {
182 T ty; // The best known type of the property (TBottom if not found)
183 SString name; // The statically known name of the string, if any
184 TriBool found; // If the property was found
185 TriBool isConst; // If the property is AttrConst
186 TriBool readOnly; // If the property is AttrIsReadonly
187 TriBool lateInit; // If the property is AttrLateInit
188 bool classInitMightRaise; // If class initialization during the
189 // property access can raise (unlike the
190 // others, this is only no or maybe).
193 template <typename T>
194 inline PropLookupResult<T>& operator|=(PropLookupResult<T>& a,
195 const PropLookupResult<T>& b) {
196 assertx(a.name == b.name);
197 a.ty |= b.ty;
198 a.found |= b.found;
199 a.isConst |= b.isConst;
200 a.readOnly |= b.readOnly;
201 a.lateInit |= b.lateInit;
202 a.classInitMightRaise |= b.classInitMightRaise;
203 return a;
206 std::string show(const PropLookupResult<Type>&);
209 * The result of Index::merge_static_type
211 template <typename T = Type> // NB: The template parameter is here to
212 // break a cyclic dependency on Type
213 struct PropMergeResult {
214 T adjusted; // The merged type, potentially adjusted according to
215 // the prop's type-constraint (it's the subtype of the
216 // merged type that would succeed).
217 TriBool throws; // Whether the mutation this merge represents
218 // can throw.
221 template <typename T>
222 inline PropMergeResult<T>& operator|=(PropMergeResult<T>& a,
223 const PropMergeResult<T>& b) {
224 a.adjusted |= b.adjusted;
225 a.throws |= b.throws;
226 return a;
229 std::string show(const PropMergeResult<Type>&);
232 * The result of Index::lookup_class_constant
234 template <typename T = Type> // NB: The template parameter is here to
235 // break a cyclic dependency on Type
236 struct ClsConstLookupResult {
237 T ty; // The best known type of the constant (might not be a
238 // scalar).
239 TriBool found; // If the constant was found
240 bool mightThrow; // If accessing the constant can throw
243 template <typename T>
244 inline ClsConstLookupResult<T>& operator|=(ClsConstLookupResult<T>& a,
245 const ClsConstLookupResult<T>& b) {
246 a.ty |= b.ty;
247 a.found |= b.found;
248 a.mightThrow |= b.mightThrow;
249 return a;
252 std::string show(const ClsConstLookupResult<Type>&);
255 * The result of Index::lookup_class_type_constant
257 template <typename T = TypeStructureResolution>
258 struct ClsTypeConstLookupResult {
259 T resolution; // The result from resolving the type-structure
260 TriBool found; // If the constant was found
261 TriBool abstract; // If the constant was abstract (this only applies
262 // to the subset which wasn't found).
265 template <typename T>
266 inline ClsTypeConstLookupResult<T>& operator|=(
267 ClsTypeConstLookupResult<T>& a,
268 const ClsTypeConstLookupResult<T>& b) {
269 a.resolution |= b.resolution;
270 if (a.found == TriBool::Yes) {
271 a.abstract = b.abstract;
272 } else if (b.found != TriBool::Yes) {
273 a.abstract |= b.abstract;
275 a.found |= b.found;
276 return a;
279 std::string show(const ClsTypeConstLookupResult<TypeStructureResolution>&);
281 //////////////////////////////////////////////////////////////////////
283 // private types
284 struct ClassInfo;
286 //////////////////////////////////////////////////////////////////////
289 * References to "resolved" entities with information in the index are
290 * in the res:: namespace.
292 * These represent handles to program entities that may have variable
293 * amounts of information. For example, we may know the name of a
294 * class in a res::Class, but do not know for sure which php::Class
295 * struct is actually associated with it.
297 namespace res {
300 * A resolved runtime Class, for a particular php::Class.
302 * Provides various lookup tables that allow querying the Class'
303 * information.
305 struct Class {
307 * Returns whether two classes are definitely same at runtime. If
308 * this function returns false, they still *may* be the same at
309 * runtime.
311 bool same(const Class&) const;
314 * Returns true if this class is definitely going to be a subtype
315 * of `o' at runtime. If this function returns false, this may
316 * still be a subtype of `o' at runtime, it just may not be known.
317 * A typical example is with "non unique" classes.
319 bool mustBeSubtypeOf(const Class& o) const;
322 * Returns false if this class is definitely not going to be a subtype
323 * of `o' at runtime. If this function returns true, this may
324 * still not be a subtype of `o' at runtime, it just may not be known.
325 * A typical example is with "non unique" classes.
327 bool maybeSubtypeOf(const Class& o) const;
330 * If this function return false, it is known that this class
331 * is in no subtype relationship with the argument Class 'o'.
332 * Returns true if this class could be a subtype of `o' at runtime.
333 * When true is returned the two classes may still be unrelated but it is
334 * not possible to tell. A typical example is with "non unique" classes.
336 bool couldBe(const Class& o) const;
339 * Returns the name of this class. Non-null guarantee.
341 SString name() const;
344 * Whether this class could possibly be an interface/interface or trait.
346 * True means it might be, false means it is not.
348 bool couldBeInterface() const;
351 * Whether this class must be an interface.
353 * True means it is, false means it might not be.
355 bool mustBeInterface() const;
357 * Returns whether this type has the no override attribute, that is, if it
358 * is a final class (explicitly marked by the user or known by the static
359 * analysis).
361 * When returning false the class is guaranteed to be final. When returning
362 * true the system cannot tell though the class may still be final.
364 bool couldBeOverriden() const;
367 * Whether this class (or its subtypes) could possibly have have
368 * a magic toBoolean() method.
370 bool couldHaveMagicBool() const;
373 * Whether this class could possibly have a derived class that is mocked.
374 * Including itself.
376 bool couldHaveMockedDerivedClass() const;
379 * Whether this class could possibly be mocked.
381 bool couldBeMocked() const;
384 * Whether this class could have reified generics
386 bool couldHaveReifiedGenerics() const;
389 * Returns whether this resolved class might distinguish being constructed
390 * dynamically versus being constructed normally (IE, might raise a notice).
392 bool mightCareAboutDynConstructs() const;
395 * Whether this class (or clases derived from it) could have const props.
397 bool couldHaveConstProp() const;
398 bool derivedCouldHaveConstProp() const;
401 * Returns the Class that is the first common ancestor between 'this' and 'o'.
402 * If there is no common ancestor std::nullopt is returned
404 Optional<Class> commonAncestor(const Class& o) const;
407 * Returns the res::Class for this Class's parent if there is one,
408 * or nullptr.
410 Optional<Class> parent() const;
413 * Returns true if we have a ClassInfo for this Class.
415 bool resolved() const {
416 return val.right() != nullptr;
420 * Returns the php::Class for this Class if there is one, or
421 * nullptr.
423 const php::Class* cls() const;
426 * Invoke the given function on every possible subclass of this
427 * class. This must be a resolved class.
429 void forEachSubclass(const std::function<void(const php::Class*)>&) const;
431 private:
432 explicit Class(Either<SString,ClassInfo*>);
433 template <bool> bool subtypeOfImpl(const Class&) const;
435 private:
436 friend std::string show(const Class&);
437 friend struct ::HPHP::HHBBC::Index;
438 friend struct ::HPHP::HHBBC::PublicSPropMutations;
439 Either<SString,ClassInfo*> val;
443 * This is an abstraction layer to represent possible runtime function
444 * resolutions.
446 * Internally, this may only know the name of the function (or method), or we
447 * may know exactly which source-code-level function it refers to, or we may
448 * only have ruled it down to one of a few functions in a class hierarchy. The
449 * interpreter can treat all these cases the same way using this.
451 struct Func {
453 * Returns the name of this function. Non-null guarantee.
455 SString name() const;
458 * If this resolved function represents exactly one php::Func, return it.
460 const php::Func* exactFunc() const;
463 * Returns whether this resolved function is definitely safe to constant fold.
465 bool isFoldable() const;
468 * Whether this function could have reified generics
470 bool couldHaveReifiedGenerics() const;
473 * Returns whether this resolved function might distinguish being called
474 * dynamically versus being called normally (IE, might raise a notice).
476 bool mightCareAboutDynCalls() const;
479 * Returns whether this resolved function might be a builtin.
481 bool mightBeBuiltin() const;
484 * Minimum/maximum bound on the number of non-variadic parameters of the
485 * function.
487 uint32_t minNonVariadicParams() const;
488 uint32_t maxNonVariadicParams() const;
491 * Coeffects
493 const RuntimeCoeffects* requiredCoeffects() const;
494 // Returns nullptr if we cant tell whether there are coeffect rules
495 const CompactVector<CoeffectRule>* coeffectRules() const;
497 struct FuncInfo;
498 struct MethTabEntryPair;
499 struct FuncFamily;
501 private:
502 friend struct ::HPHP::HHBBC::Index;
503 struct FuncName {
504 FuncName(SString n, bool r) : name{n}, renamable{r} {}
505 bool operator==(FuncName o) const { return name == o.name; }
506 SString name;
507 bool renamable;
509 struct MethodName {
510 bool operator==(MethodName o) const { return name == o.name; }
511 SString name;
513 using Rep = boost::variant< FuncName
514 , MethodName
515 , FuncInfo*
516 , const MethTabEntryPair*
517 , FuncFamily*
520 private:
521 Func(const Index*, Rep);
522 friend std::string show(const Func&);
524 private:
525 const Index* index;
526 Rep val;
530 * Produce a trace-able string for a res::Func or res::Class.
532 std::string show(const Func&);
533 std::string show(const Class&);
537 //////////////////////////////////////////////////////////////////////
540 * This class encapsulates the known facts about the program, with a
541 * whole-program view.
543 * This structure contains unowned pointers into the php::Program it
544 * was created for. It should not out-live the Program.
546 * The const member functions of this class are thread safe for
547 * concurrent reads and writes. The non-const functions should be
548 * called in a single threaded context only (they are used during the
549 * "update" step in between whole program analysis rounds).
551 struct Index {
553 * Create an Index for a php::Program. Performs some initial
554 * analysis of the program.
556 explicit Index(php::Program*);
559 * This class must not be destructed after its associated
560 * php::Program.
562 ~Index();
565 * The index operates in two modes: frozen, and unfrozen.
567 * Conceptually, the index is mutable and may acquire new
568 * information until it has been frozen, and once frozen, it retains
569 * the information it had at the point it was frozen.
571 * The reason this exists is because certain functions on the index
572 * may cause it to need to consult information in the bodies of
573 * functions other than the Context passed in. Specifically, if the
574 * interpreter tries to look up the return type for a callee in a
575 * given CallContext, the index may choose to recursively invoke
576 * type inference on that callee's function body to see if more
577 * precise information can be determined, unless it is frozen.
579 * This is fine until the final pass, because all bytecode is
580 * read-only at that stage. However, in the final pass, other
581 * threads might be optimizing a callee's bytecode and changing it,
582 * so we should not be reading from it to perform type inference
583 * concurrently. Freezing the index tells it it can't do that
584 * anymore.
586 * These are the functions to query and transition to frozen state.
588 bool frozen() const;
589 void freeze();
590 void thaw();
593 * Throw away data structures that won't be needed during or after
594 * the final pass. Currently the dependency map, which can take a
595 * long time to destroy.
597 void cleanup_for_final();
600 * Throw away data structures that won't be needed after the emit
601 * stage.
603 void cleanup_post_emit(php::ProgramPtr program);
606 * The Index contains a Builder for an ArrayTypeTable.
608 * If we're creating assert types with options.InsertAssertions, we
609 * need to keep track of which array types exist in the whole
610 * program in order to include it in the repo.
612 std::unique_ptr<ArrayTypeTable::Builder>& array_table_builder() const;
615 * Find all the closures created inside the context of a given
616 * php::Class.
618 const CompactVector<const php::Class*>*
619 lookup_closures(const php::Class*) const;
622 * Find all the extra methods associated with a class from its
623 * traits.
625 const hphp_fast_set<const php::Func*>*
626 lookup_extra_methods(const php::Class*) const;
629 * Try to find a res::Class for a given php::Class.
631 * Note, the returned class may or may not be *defined* at the
632 * program point you care about (it could be non-hoistable, even
633 * though it's unique, for example).
635 * Returns a name-only resolution if there are no legal
636 * instantiations of the class, or if there is more than one.
638 res::Class resolve_class(const php::Class*) const;
641 * Try to resolve which class will be the class named `name' from a
642 * given context, if we can resolve it to a single class.
644 * Note, the returned class may or may not be *defined* at the
645 * program point you care about (it could be non-hoistable, even
646 * though it's unique, for example).
648 * Returns std::nullopt if we can't prove the supplied name must be a
649 * object type. (E.g. if there are type aliases.)
651 Optional<res::Class> resolve_class(Context, SString name) const;
654 * Find a type-alias with the given name. If a nullptr is returned,
655 * then no type-alias exists with that name.
657 const php::TypeAlias* lookup_type_alias(SString name) const;
660 * Try to resolve self/parent types for the given context
662 Optional<res::Class> selfCls(const Context& ctx) const;
663 Optional<res::Class> parentCls(const Context& ctx) const;
665 template <typename T>
666 struct ResolvedInfo {
667 AnnotType type;
668 bool nullable;
669 T value;
673 * Try to resolve name, looking through TypeAliases and enums.
675 ResolvedInfo<Optional<res::Class>> resolve_type_name(SString name) const;
678 * Resolve a closure class.
680 * Returns both a resolved Class, and the actual php::Class for the
681 * closure.
683 std::pair<res::Class,php::Class*>
684 resolve_closure_class(Context ctx, int32_t idx) const;
687 * Return a resolved class for a builtin class.
689 * Pre: `name' must be the name of a class defined in a systemlib.
691 res::Class builtin_class(SString name) const;
694 * Try to resolve a function named `name' from a given context.
696 * Note, the returned function may or may not be defined at the
697 * program point (it could require a function autoload that might
698 * fail).
700 res::Func resolve_func(Context, SString name) const;
703 * Try to resolve a class method named `name' with a given Context
704 * and class type.
706 * Pre: clsType.subtypeOf(BCls)
708 res::Func resolve_method(Context, Type clsType, SString name) const;
711 * Try to resolve a class constructor for the supplied class type.
713 * Returns: std::nullopt if it can't at least figure out a func
714 * family for the call.
716 Optional<res::Func>
717 resolve_ctor(Context, res::Class rcls, bool exact) const;
720 * Give the Type in our type system that matches an hhvm
721 * TypeConstraint, subject to the information in this Index.
723 * This function returns a subtype of Cell, although TypeConstraints
724 * at runtime can match reference parameters. The caller should
725 * make sure to handle that case.
727 * For soft constraints (@), this function returns Cell.
729 * For some non-soft constraints (such as "Stringish"), this
730 * function may return a Type that is a strict supertype of the
731 * constraint's type.
733 * If something is known about the type of the object against which
734 * the constraint will be checked, it can be passed in to help
735 * disambiguate certain constraints (useful because we don't support
736 * arbitrary unions, or intersection).
738 Type lookup_constraint(Context, const TypeConstraint&,
739 const Type& t = TCell) const;
742 * If this function returns true, it is safe to assume that Type t
743 * will always satisfy TypeConstraint tc at run time.
745 bool satisfies_constraint(Context, const Type& t,
746 const TypeConstraint& tc) const;
749 * Returns true if the given type-hint (declared on the given class) might not
750 * be enforced at runtime (IE, it might map to mixed or be soft).
752 bool prop_tc_maybe_unenforced(const php::Class& propCls,
753 const TypeConstraint& tc) const;
756 * Returns true if the type constraint can contain a reified type
757 * Currently, only classes and interfaces are supported
759 bool could_have_reified_type(Context ctx, const TypeConstraint& tc) const;
762 * Lookup metadata about the constant access `cls'::`name', in the
763 * current context `ctx'. The returned metadata not only includes
764 * the best known type of the constant, but whether it is definitely
765 * found, and whether accessing the constant might throw. This
766 * function is responsible for walking the class hierarchy to find
767 * all possible constants and combining the results. This is
768 * intended to be the source of truth about constants during
769 * analysis.
771 * This function only looks up non-type, non-context constants.
773 ClsConstLookupResult<>
774 lookup_class_constant(Context ctx, const Type& cls, const Type& name) const;
777 * Lookup metadata about the constant access `cls'::`name', where
778 * that constant is meant to be a type-constant. The returned
779 * metadata includes the best known type of the resolved
780 * type-structure, whether it was found, and whether it was
781 * abstract. This is intended to be the source of truth about
782 * type-constants during analysis. The returned type-structure type
783 * will always be static.
785 * By default, lookup_class_type_constant calls
786 * resolve_type_structure to resolve any found type-structure. This
787 * behavior can be overridden by providing a customer resolver.
789 using ClsTypeConstLookupResolver =
790 std::function<TypeStructureResolution(const php::Const&,const php::Class&)>;
792 ClsTypeConstLookupResult<>
793 lookup_class_type_constant(
794 const Type& cls,
795 const Type& name,
796 const ClsTypeConstLookupResolver& resolver = {}) const;
799 * Lookup what the best known Type for a constant would be, using a
800 * given Index and Context, if a constant of that name were defined.
802 Type lookup_constant(Context ctx, SString cnsName) const;
805 * Return true if the return value of the function might depend on arg.
807 bool func_depends_on_arg(const php::Func* func, int arg) const;
810 * If func is effect-free when called with args, and it returns a constant,
811 * return that constant; otherwise return TInitCell.
813 Type lookup_foldable_return_type(Context ctx,
814 const php::Func* func,
815 Type ctxType,
816 CompactVector<Type> args) const;
818 * Return the best known return type for a resolved function, in a
819 * context insensitive way. Returns TInitCell at worst.
821 Type lookup_return_type(Context, MethodsInfo*, res::Func,
822 Dep dep = Dep::ReturnTy) const;
825 * Return the best known return type for a resolved function, given
826 * the supplied calling context. Returns TInitCell at worst.
828 * During analyze phases, this function may re-enter analyze in
829 * order to interpret the callee with these argument types.
831 Type lookup_return_type(Context caller,
832 MethodsInfo*,
833 const CompactVector<Type>& args,
834 const Type& context,
835 res::Func,
836 Dep dep = Dep::ReturnTy) const;
839 * Look up raw return type information for an unresolved
840 * function. This is the best known return type, and the number of
841 * refinements done to that type.
843 * This function does not register a dependency on the return type
844 * information.
846 * Nothing may be writing to the index when this function is used,
847 * but concurrent readers are allowed.
849 std::pair<Type, size_t> lookup_return_type_raw(const php::Func*) const;
852 * Return the best known types of a closure's used variables (on
853 * entry to the closure). The function is the closure body.
855 * If move is true, the value will be moved out of the index. This
856 * should only be done at emit time. (note that the only other user
857 * of this info is analysis, which only uses it when processing the
858 * owning class, so its safe to kill after emitting the owning
859 * unit).
861 CompactVector<Type>
862 lookup_closure_use_vars(const php::Func*,
863 bool move = false) const;
866 * Return the availability of $this on entry to the provided method.
867 * If the Func provided is not a method of a class false is
868 * returned.
870 bool lookup_this_available(const php::Func*) const;
873 * Returns the parameter preparation kind (if known) for parameter
874 * `paramId' on the given resolved Func.
876 PrepKind lookup_param_prep(Context, res::Func, uint32_t paramId) const;
879 * Returns the number of inout parameters expected by func (if known).
881 Optional<uint32_t> lookup_num_inout_params(Context, res::Func) const;
884 * Returns whether the function's return value is readonly
886 TriBool lookup_return_readonly(Context, res::Func) const;
889 * Returns whether the function is marked as readonly
891 TriBool lookup_readonly_this(Context, res::Func) const;
894 * Returns the control-flow insensitive inferred private instance
895 * property types for a Class. The Class doesn't need to be
896 * resolved, because private properties don't depend on the
897 * inheritance hierarchy.
899 * The Index tracks the largest types for private properties that
900 * are guaranteed to hold at any program point.
902 * If move is true, the value will be moved out of the index. This
903 * should only be done at emit time. (note that the only other user
904 * of this info is analysis, which only uses it when processing the
905 * owning class, so its safe to kill after emitting the owning
906 * unit).
908 PropState lookup_private_props(const php::Class*,
909 bool move = false) const;
912 * Returns the control-flow insensitive inferred private static
913 * property types for a Class. The class doesn't need to be
914 * resolved for the same reasons as for instance properties.
916 * The Index tracks the largest types for private static properties
917 * that are guaranteed to hold at any program point.
919 * If move is true, the value will be moved out of the index. This
920 * should only be done at emit time. (note that the only other user
921 * of this info is analysis, which only uses it when processing the
922 * owning class, so its safe to kill after emitting the owning
923 * unit).
925 PropState lookup_private_statics(const php::Class*,
926 bool move = false) const;
927 PropState lookup_public_statics(const php::Class*) const;
930 * Lookup metadata about the static property access `cls'::`name',
931 * in the current context `ctx'. The returned metadata not only
932 * includes the best known type of the property, but whether it is
933 * definitely found, and whether the access might raise for various
934 * reasons. This function is responsible for walking the class
935 * hierarchy to find the appropriate property while applying
936 * accessibility rules. This is intended to be the source of truth
937 * about static properties during analysis.
939 PropLookupResult<> lookup_static(Context ctx,
940 const PropertiesInfo& privateProps,
941 const Type& cls,
942 const Type& name) const;
945 * Lookup if initializing (which is a side-effect of several bytecodes) the
946 * given class might raise.
948 bool lookup_class_init_might_raise(Context, res::Class) const;
951 * Lookup the best known type for a public (non-static) property. Since we
952 * don't do analysis on public properties, this just inferred from the
953 * property's type-hint (if enforced).
955 Type lookup_public_prop(const Type& cls, const Type& name) const;
956 Type lookup_public_prop(const php::Class* cls, SString name) const;
959 * We compute the interface vtables in a separate thread. It needs
960 * to be joined (in single threaded context) before calling
961 * lookup_iface_vtable_slot.
963 void join_iface_vtable_thread() const;
966 * Returns the computed vtable slot for the given class, if it's an interface
967 * that was given a vtable slot. No two interfaces implemented by the same
968 * class will share the same vtable slot. May return kInvalidSlot, if the
969 * given class isn't an interface or if it wasn't assigned a slot.
971 Slot lookup_iface_vtable_slot(const php::Class*) const;
974 * Return the DependencyContext for ctx.
976 DependencyContext dependency_context(const Context& ctx) const;
979 * Determine whether to use class-at-a-time, or function-at-a-time
980 * dependencies.
982 * Must be called in single-threaded context.
984 void use_class_dependencies(bool f);
987 * Merge the type `val' into the known type for static property
988 * `cls'::`name'. Depending on what we know about `cls' and `name',
989 * this might affect multiple properties. This function is
990 * responsible for walking the class hierarchy to find the
991 * appropriate property while applying accessibility
992 * rules. Mutations of AttrConst properties are ignored unless
993 * `ignoreConst' is set to true. If `checkUB' is true, upper-bound
994 * type constraints are consulted in addition to the normal type
995 * constraints.
997 * The result tells you the subtype of val that would be
998 * successfully set (according to the type constraints), and if the
999 * mutation would throw or not.
1001 PropMergeResult<> merge_static_type(Context ctx,
1002 PublicSPropMutations& publicMutations,
1003 PropertiesInfo& privateProps,
1004 const Type& cls,
1005 const Type& name,
1006 const Type& val,
1007 bool checkUB = false,
1008 bool ignoreConst = false,
1009 bool mustBeReadOnly = false) const;
1012 * Initialize the initial types for public static properties. This should be
1013 * done after rewriting initial property values, as that affects the types.
1015 void init_public_static_prop_types();
1018 * Initialize the initial "may have bad initial value" bit for
1019 * properties. By initially setting this before analysis, we save
1020 * redundant re-analyzes.
1022 void preinit_bad_initial_prop_values();
1025 * Attempt to pre-resolve as many type-structures as possible in
1026 * type-constants and type-aliases.
1028 void preresolve_type_structures(php::Program&);
1031 * Refine the types of the class constants defined by an 86cinit,
1032 * based on a round of analysis.
1034 * No other threads should be using ctx.cls->constants or deps when
1035 * this function is called.
1037 * Merges the set of Contexts that depended on the constants defined
1038 * by this 86cinit.
1040 void refine_class_constants(
1041 const Context& ctx,
1042 const CompactVector<std::pair<size_t, Type>>& resolved,
1043 DependencyContextSet& deps);
1046 * Refine the types of the constants defined by a function, based on
1047 * a round of analysis.
1049 * Constants not defined by a pseudomain are considered unknowable
1051 * No other threads should be calling functions on this Index when
1052 * this function is called.
1054 * Merges the set of Contexts that depended on the constants defined
1055 * by this php::Func into deps.
1057 void refine_constants(const FuncAnalysisResult& fa,
1058 DependencyContextSet& deps);
1061 * Refine the return type for a function, based on a round of
1062 * analysis.
1064 * No other threads should be calling functions on this Index when
1065 * this function is called.
1067 * Merges the set of Contexts that depended on the return type of
1068 * this php::Func into deps.
1070 void refine_return_info(const FuncAnalysisResult& fa,
1071 DependencyContextSet& deps);
1074 * Refine the used var types for a closure, based on a round of
1075 * analysis.
1077 * No other threads should be calling functions on this Index when
1078 * this function is called.
1080 * Returns: true if the types have changed.
1082 bool refine_closure_use_vars(const php::Class*,
1083 const CompactVector<Type>&);
1086 * Refine the private property types for a class, based on a round
1087 * of analysis.
1089 * No other threads should be calling functions on this Index when
1090 * this function is called.
1092 void refine_private_props(const php::Class* cls,
1093 const PropState&);
1096 * Refine the static private property types for a class, based on a
1097 * round of analysis.
1099 * No other threads should be calling functions on this Index when
1100 * this function is called.
1102 void refine_private_statics(const php::Class* cls,
1103 const PropState&);
1106 * Record in the index that the given set of public static property mutations
1107 * has been found while analyzing the given function. During a round of
1108 * analysis, the mutations are gathered from the analysis results for each
1109 * function, recorded in the index, and then refine_public_statics is called
1110 * to process the mutations and update the index.
1112 * No other threads should be calling functions on this Index when this
1113 * function is called.
1115 void record_public_static_mutations(const php::Func& func,
1116 PublicSPropMutations mutations);
1120 * If we resolve the intial value of a public property, we need to
1121 * tell the refine_public_statics phase about it, because the init
1122 * value won't be included in the mutations any more.
1124 * Note that we can't modify the initial value here, because other
1125 * threads might be reading it (via loookup_public_static), so we
1126 * set a flag to tell us to update it during the next
1127 * refine_public_statics pass.
1129 void update_static_prop_init_val(const php::Class* cls,
1130 SString name) const;
1132 * After a round of analysis with all the public static property mutations
1133 * being recorded with record_public_static_mutations, the types can be
1134 * reflected into the index for use during another type inference pass.
1136 * No other threads should be calling functions on this Index when this
1137 * function is called.
1139 * Merges the set of Contexts that depended on a public static property whose
1140 * type has changed.
1142 void refine_public_statics(DependencyContextSet& deps);
1145 * Refine whether the given class has properties with initial values which
1146 * might violate their type-hints.
1148 * No other threads should be calling functions on this Index when this
1149 * function is called.
1151 void refine_bad_initial_prop_values(const php::Class* cls,
1152 bool value,
1153 DependencyContextSet& deps);
1156 * Mark any properties in cls that definitely do not redeclare a property in
1157 * the parent, which has an inequivalent type-hint.
1159 void mark_no_bad_redeclare_props(php::Class& cls) const;
1162 * Rewrite the initial values of any AttrSystemInitialValue properties to
1163 * something more suitable for its type-hint, and add AttrNoImplicitNullable
1164 * where appropriate.
1166 * This must be done before any analysis is done, as the initial values
1167 * affects the analysis.
1169 void rewrite_default_initial_values(php::Program&) const;
1172 * Return true if the resolved function supports async eager return.
1174 Optional<bool> supports_async_eager_return(res::Func rfunc) const;
1177 * Return true if the function is effect free.
1179 bool is_effect_free(res::Func rfunc) const;
1180 bool is_effect_free(const php::Func* func) const;
1183 * Do any necessary fixups to a return type.
1185 * Note that eg for an async function it will map Type to
1186 * WaitH<Type>.
1188 void fixup_return_type(const php::Func*, Type&) const;
1191 * Return true if we know for sure that one php::Class must derive
1192 * from another at runtime, in all possible instantiations.
1194 bool must_be_derived_from(const php::Class*,
1195 const php::Class*) const;
1197 struct IndexData;
1198 private:
1199 Index(const Index&) = delete;
1200 Index& operator=(Index&&) = delete;
1202 private:
1203 friend struct PublicSPropMutations;
1205 res::Func resolve_func_helper(const php::Func*, SString) const;
1206 res::Func do_resolve(const php::Func*) const;
1207 bool could_be_related(const php::Class*,
1208 const php::Class*) const;
1210 template<bool getSuperType>
1211 Type get_type_for_constraint(Context,
1212 const TypeConstraint&,
1213 const Type&) const;
1215 struct ConstraintResolution;
1218 * Try to resolve name in the given context. Follows TypeAliases.
1220 ConstraintResolution resolve_named_type(
1221 const Context& ctx, SString name, const Type& candidate) const;
1223 ConstraintResolution get_type_for_annotated_type(
1224 Context ctx, AnnotType annot, bool nullable,
1225 SString name, const Type& candidate) const;
1227 void init_return_type(const php::Func* func);
1229 ResolvedInfo<boost::variant<boost::blank,SString,ClassInfo*>>
1230 resolve_type_name_internal(SString name) const;
1232 private:
1233 std::unique_ptr<IndexData> const m_data;
1236 //////////////////////////////////////////////////////////////////////
1239 * Used for collecting all mutations of public static property types.
1241 struct PublicSPropMutations {
1242 private:
1243 friend struct Index;
1245 struct KnownKey {
1246 bool operator<(KnownKey o) const {
1247 if (cinfo != o.cinfo) return cinfo < o.cinfo;
1248 return prop < o.prop;
1251 ClassInfo* cinfo;
1252 SString prop;
1255 using UnknownMap = std::map<SString,Type>;
1256 using KnownMap = std::map<KnownKey,Type>;
1258 // Public static property mutations are actually rare, so defer allocating the
1259 // maps until we actually see one.
1260 struct Data {
1261 bool m_nothing_known{false};
1262 UnknownMap m_unknown;
1263 KnownMap m_known;
1265 std::unique_ptr<Data> m_data;
1267 Data& get();
1269 void mergeKnown(const ClassInfo* ci, const php::Prop& prop, const Type& val);
1270 void mergeUnknownClass(SString prop, const Type& val);
1271 void mergeUnknown(Context);
1274 //////////////////////////////////////////////////////////////////////