kill unsafe
[hiphop-php.git] / hphp / hhbbc / index.h
blobcfaf2ad6a897adb0c4e97d52d061fc11f32eb7ab
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_INDEX_H_
17 #define incl_HHBBC_INDEX_H_
19 #include <memory>
20 #include <tuple>
21 #include <vector>
22 #include <map>
23 #include <exception>
25 #include <boost/variant.hpp>
26 #include <tbb/concurrent_hash_map.h>
28 #include <folly/synchronization/Baton.h>
29 #include <folly/Optional.h>
30 #include <folly/Hash.h>
32 #include "hphp/util/compact-vector.h"
33 #include "hphp/util/either.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;
52 extern const Type TTop;
54 namespace php {
55 struct Class;
56 struct Const;
57 struct Func;
58 struct Unit;
59 struct Program;
62 //////////////////////////////////////////////////////////////////////
65 * This module contains functions for building and querying an Index
66 * of data relating to "resolved" versions of the names in of a
67 * php::Program. It also records dependencies so it is possible to
68 * tell which parts of the program may be interested in new inferred
69 * information about other parts of the program.
71 * The main entry point here is the Index class. The Index is built
72 * after parse time, and then analysis can query it for information.
75 //////////////////////////////////////////////////////////////////////
78 * A DependencyContext encodes enough of the context to record a dependency - a
79 * php::Func, if we're doing private property analysis and its a suitable class,
80 * a php::Class, or a public static property with a particular name.
83 enum class DependencyContextType : uint16_t {
84 Func,
85 Class,
86 PropName
89 using DependencyContext = CompactTaggedPtr<const void, DependencyContextType>;
91 struct DependencyContextLess {
92 bool operator()(const DependencyContext& a,
93 const DependencyContext& b) const {
94 return a.getOpaque() < b.getOpaque();
98 struct DependencyContextEquals {
99 bool operator()(const DependencyContext& a,
100 const DependencyContext& b) const {
101 return a.getOpaque() == b.getOpaque();
105 struct DependencyContextHash {
106 size_t operator()(const DependencyContext& d) const {
107 return pointer_hash<void>{}(reinterpret_cast<void*>(d.getOpaque()));
111 struct DependencyContextHashCompare : DependencyContextHash {
112 bool equal(const DependencyContext& a, const DependencyContext& b) const {
113 return a.getOpaque() == b.getOpaque();
115 size_t hash(const DependencyContext& d) const { return (*this)(d); }
118 using DependencyContextSet = hphp_hash_set<DependencyContext,
119 DependencyContextHash,
120 DependencyContextEquals>;
121 using ContextSet = hphp_hash_set<Context, ContextHash>;
123 std::string show(Context);
125 using ConstantMap = hphp_hash_map<SString, Cell>;
128 * State of properties on a class. Map from property name to its
129 * Type.
131 template <typename T = Type>
132 struct PropStateElem {
133 T ty;
134 const TypeConstraint* tc = nullptr;
136 bool operator==(const PropStateElem<T>& o) const {
137 return ty == o.ty && tc == o.tc;
140 using PropState = std::map<LSString,PropStateElem<>>;
142 //////////////////////////////////////////////////////////////////////
144 // private types
145 struct ClassInfo;
147 //////////////////////////////////////////////////////////////////////
150 * References to "resolved" entities with information in the index are
151 * in the res:: namespace.
153 * These represent handles to program entities that may have variable
154 * amounts of information. For example, we may know the name of a
155 * class in a res::Class, but do not know for sure which php::Class
156 * struct is actually associated with it.
158 namespace res {
161 * A resolved runtime Class, for a particular php::Class.
163 * Provides various lookup tables that allow querying the Class'
164 * information.
166 struct Class {
168 * Returns whether two classes are definitely same at runtime. If
169 * this function returns false, they still *may* be the same at
170 * runtime.
172 bool same(const Class&) const;
175 * Returns true if this class is definitely going to be a subtype
176 * of `o' at runtime. If this function returns false, this may
177 * still be a subtype of `o' at runtime, it just may not be known.
178 * A typical example is with "non unique" classes.
180 bool mustBeSubtypeOf(const Class& o) const;
183 * Returns false if this class is definitely not going to be a subtype
184 * of `o' at runtime. If this function returns true, this may
185 * still not be a subtype of `o' at runtime, it just may not be known.
186 * A typical example is with "non unique" classes.
188 bool maybeSubtypeOf(const Class& o) const;
191 * If this function return false, it is known that this class
192 * is in no subtype relationship with the argument Class 'o'.
193 * Returns true if this class could be a subtype of `o' at runtime.
194 * When true is returned the two classes may still be unrelated but it is
195 * not possible to tell. A typical example is with "non unique" classes.
197 bool couldBe(const Class& o) const;
200 * Returns the name of this class. Non-null guarantee.
202 SString name() const;
205 * Whether this class could possibly be an interface/interface or trait.
207 * True means it might be, false means it is not.
209 bool couldBeInterface() const;
210 bool couldBeInterfaceOrTrait() const;
213 * Returns whether this type has the no override attribute, that is, if it
214 * is a final class (explicitly marked by the user or known by the static
215 * analysis).
217 * When returning false the class is guaranteed to be final. When returning
218 * true the system cannot tell though the class may still be final.
220 bool couldBeOverriden() const;
223 * Whether this class (or its subtypes) could possibly have have
224 * certain magic methods.
226 bool couldHaveMagicGet() const;
229 * Whether this class (or its subtypes) could possibly have have
230 * a magic toBoolean() method.
232 bool couldHaveMagicBool() const;
235 * Whether this class could possibly have a derived class that is mocked.
236 * Including itself.
238 bool couldHaveMockedDerivedClass() const;
241 * Whether this class could possibly be mocked.
243 bool couldBeMocked() const;
246 * Whether this class could have reified generics
248 bool couldHaveReifiedGenerics() const;
251 * Returns whether this resolved class might distinguish being constructed
252 * dynamically versus being constructed normally (IE, might raise a notice).
254 bool mightCareAboutDynConstructs() const;
257 * Returns the Class that is the first common ancestor between 'this' and 'o'.
258 * If there is no common ancestor folly::none is returned
260 folly::Optional<Class> commonAncestor(const Class& o) const;
263 * Returns the res::Class for this Class's parent if there is one,
264 * or nullptr.
266 folly::Optional<Class> parent() const;
269 * Returns true if we have a ClassInfo for this Class.
271 bool resolved() const {
272 return val.right() != nullptr;
276 * Returns the php::Class for this Class if there is one, or
277 * nullptr.
279 const php::Class* cls() const;
281 private:
282 Class(const Index*, Either<SString,ClassInfo*>);
283 template <bool> bool subtypeOfImpl(const Class&) const;
285 private:
286 friend std::string show(const Class&);
287 friend struct ::HPHP::HHBBC::Index;
288 friend struct ::HPHP::HHBBC::PublicSPropMutations;
289 const Index* index;
290 Either<SString,ClassInfo*> val;
294 * This is an abstraction layer to represent possible runtime function
295 * resolutions.
297 * Internally, this may only know the name of the function (or method), or we
298 * may know exactly which source-code-level function it refers to, or we may
299 * only have ruled it down to one of a few functions in a class hierarchy. The
300 * interpreter can treat all these cases the same way using this.
302 struct Func {
304 * Returns whether two res::Funcs definitely mean the func at
305 * runtime.
307 * Note: this is potentially pessimistic for its use in ActRec state
308 * merging right now, but not incorrect.
310 bool same(const Func&) const;
313 * Returns the name of this function. Non-null guarantee.
315 SString name() const;
318 * If this resolved function represents exactly one php::Func, return it.
320 const php::Func* exactFunc() const;
323 * Returns whether this resolved function could possibly be going through a
324 * magic call, in the magic way.
326 * That is, if was resolved as part of a direct call to an __call method,
327 * this will say true. If it was resolved as part as some normal method
328 * call, and we haven't proven that there's no way an __call dispatch could
329 * be involved, this will say false.
331 bool cantBeMagicCall() const;
334 * Returns whether this resolved function is definitely safe to constant fold.
336 bool isFoldable() const;
339 * Whether this function could have reified generics
341 bool couldHaveReifiedGenerics() const;
344 * Returns whether this resolved function might distinguish being called
345 * dynamically versus being called normally (IE, might raise a notice).
347 bool mightCareAboutDynCalls() const;
350 * Returns whether this resolved function might be a builtin.
352 bool mightBeBuiltin() const;
354 struct FuncInfo;
355 struct MethTabEntryPair;
356 struct FuncFamily;
358 private:
359 friend struct ::HPHP::HHBBC::Index;
360 struct FuncName {
361 FuncName(SString n, bool r) : name{n}, renamable{r} {}
362 bool operator==(FuncName o) const { return name == o.name; }
363 SString name;
364 bool renamable;
366 struct MethodName {
367 bool operator==(MethodName o) const { return name == o.name; }
368 SString name;
370 using Rep = boost::variant< FuncName
371 , MethodName
372 , FuncInfo*
373 , const MethTabEntryPair*
374 , FuncFamily*
377 private:
378 Func(const Index*, Rep);
379 friend std::string show(const Func&);
381 private:
382 const Index* index;
383 Rep val;
387 * Produce a trace-able string for a res::Func or res::Class.
389 std::string show(const Func&);
390 std::string show(const Class&);
394 //////////////////////////////////////////////////////////////////////
397 * This class encapsulates the known facts about the program, with a
398 * whole-program view.
400 * This structure contains unowned pointers into the php::Program it
401 * was created for. It should not out-live the Program.
403 * The const member functions of this class are thread safe for
404 * concurrent reads and writes. The non-const functions should be
405 * called in a single threaded context only (they are used during the
406 * "update" step in between whole program analysis rounds).
408 struct Index {
410 * Throwing a rebuild exception indicates that the index needs to
411 * be rebuilt.
413 * The exception should be passed to the Index constructor.
415 struct rebuild : std::exception {
416 explicit rebuild(std::vector<std::pair<SString, SString>> ca) :
417 class_aliases(std::move(ca)) {}
418 private:
419 friend struct Index;
420 std::vector<std::pair<SString, SString>> class_aliases;
424 * Create an Index for a php::Program. Performs some initial
425 * analysis of the program.
427 explicit Index(php::Program*, rebuild* = nullptr);
430 * This class must not be destructed after its associated
431 * php::Program.
433 ~Index();
436 * The index operates in two modes: frozen, and unfrozen.
438 * Conceptually, the index is mutable and may acquire new
439 * information until it has been frozen, and once frozen, it retains
440 * the information it had at the point it was frozen.
442 * The reason this exists is because certain functions on the index
443 * may cause it to need to consult information in the bodies of
444 * functions other than the Context passed in. Specifically, if the
445 * interpreter tries to look up the return type for a callee in a
446 * given CallContext, the index may choose to recursively invoke
447 * type inference on that callee's function body to see if more
448 * precise information can be determined, unless it is frozen.
450 * This is fine until the final pass, because all bytecode is
451 * read-only at that stage. However, in the final pass, other
452 * threads might be optimizing a callee's bytecode and changing it,
453 * so we should not be reading from it to perform type inference
454 * concurrently. Freezing the index tells it it can't do that
455 * anymore.
457 * These are the functions to query and transition to frozen state.
459 bool frozen() const;
460 void freeze();
461 void thaw();
464 * Throw away data structures that won't be needed during the emit
465 * stage (or beyond).
467 void cleanup_for_emit(folly::Baton<>* done);
470 * The Index contains a Builder for an ArrayTypeTable.
472 * If we're creating assert types with options.InsertAssertions, we
473 * need to keep track of which array types exist in the whole
474 * program in order to include it in the repo.
476 std::unique_ptr<ArrayTypeTable::Builder>& array_table_builder() const;
479 * Find all the closures created inside the context of a given
480 * php::Class.
482 const CompactVector<const php::Class*>*
483 lookup_closures(const php::Class*) const;
486 * Find all the extra methods associated with a class from its
487 * traits.
489 const hphp_fast_set<php::Func*>*
490 lookup_extra_methods(const php::Class*) const;
493 * Attempt to record a new alias in the index. May be called from
494 * multi-threaded contexts, so doesn't actually update the index
495 * (call update_class_aliases to do that). Returns false if it would
496 * violate any current uniqueness assumptions.
498 bool register_class_alias(SString orig, SString alias) const;
501 * Add any aliases that have been registered since the last call to
502 * update_class_aliases to the index. Must be called from a single
503 * threaded context.
505 void update_class_aliases();
508 * Try to find a res::Class for a given php::Class.
510 * Note, the returned class may or may not be *defined* at the
511 * program point you care about (it could be non-hoistable, even
512 * though it's unique, for example).
514 * Returns a name-only resolution if there are no legal
515 * instantiations of the class, or if there is more than one.
517 res::Class resolve_class(const php::Class*) const;
520 * Try to resolve which class will be the class named `name' from a
521 * given context, if we can resolve it to a single class.
523 * Note, the returned class may or may not be *defined* at the
524 * program point you care about (it could be non-hoistable, even
525 * though it's unique, for example).
527 * Returns folly::none if we can't prove the supplied name must be a
528 * object type. (E.g. if there are type aliases.)
530 folly::Optional<res::Class> resolve_class(Context, SString name) const;
533 * Try to resolve self/parent types for the given context
535 folly::Optional<res::Class> selfCls(const Context& ctx) const;
536 folly::Optional<res::Class> parentCls(const Context& ctx) const;
538 template <typename T>
539 struct ResolvedInfo {
540 AnnotType type;
541 bool nullable;
542 T value;
546 * Try to resolve name, looking through TypeAliases and enums.
548 ResolvedInfo<folly::Optional<res::Class>>
549 resolve_type_name(SString name) const;
552 * Resolve a closure class.
554 * Returns both a resolved Class, and the actual php::Class for the
555 * closure.
557 std::pair<res::Class,php::Class*>
558 resolve_closure_class(Context ctx, int32_t idx) const;
561 * Return a resolved class for a builtin class.
563 * Pre: `name' must be the name of a class defined in a systemlib.
565 res::Class builtin_class(SString name) const;
568 * Try to resolve a function named `name' from a given context.
570 * Note, the returned function may or may not be defined at the
571 * program point (it could require a function autoload that might
572 * fail).
574 res::Func resolve_func(Context, SString name) const;
577 * Try to resolve a class method named `name' with a given Context
578 * and class type.
580 * Pre: clsType.subtypeOf(BCls)
582 res::Func resolve_method(Context, Type clsType, SString name) const;
585 * Try to resolve a class constructor for the supplied class type.
587 * Returns: folly::none if it can't at least figure out a func
588 * family for the call.
590 folly::Optional<res::Func>
591 resolve_ctor(Context, res::Class rcls, bool exact) const;
594 * Give the Type in our type system that matches an hhvm
595 * TypeConstraint, subject to the information in this Index.
597 * This function returns a subtype of Cell, although TypeConstraints
598 * at runtime can match reference parameters. The caller should
599 * make sure to handle that case.
601 * For soft constraints (@), this function returns Cell.
603 * For some non-soft constraints (such as "Stringish"), this
604 * function may return a Type that is a strict supertype of the
605 * constraint's type.
607 * If something is known about the type of the object against which
608 * the constraint will be checked, it can be passed in to help
609 * disambiguate certain constraints (useful because we don't support
610 * arbitrary unions, or intersection).
612 Type lookup_constraint(Context, const TypeConstraint&,
613 const Type& t = TTop) const;
616 * If this function returns true, it is safe to assume that Type t
617 * will always satisfy TypeConstraint tc at run time.
619 bool satisfies_constraint(Context, const Type& t,
620 const TypeConstraint& tc) const;
623 * Returns true if the given type-hint (declared on the given class) might not
624 * be enforced at runtime (IE, it might map to mixed or be soft).
626 bool prop_tc_maybe_unenforced(const php::Class& propCls,
627 const TypeConstraint& tc) const;
630 * Returns true if the type constraint can contain a reified type
631 * Currently, only classes and interfaces are supported
633 bool could_have_reified_type(const TypeConstraint& tc) const;
636 * Lookup what the best known Type for a class constant would be,
637 * using a given Index and Context, if a class of that name were
638 * loaded.
639 * If allow_tconst is not set, type constants will not be returned.
640 * lookup_class_const_ptr version returns the statically known version
641 * of the const if it can find it, otherwise returns nullptr.
643 Type lookup_class_constant(Context, res::Class, SString cns,
644 bool allow_tconst) const;
645 const php::Const* lookup_class_const_ptr(Context, res::Class, SString cns,
646 bool allow_tconst) const;
649 * Lookup what the best known Type for a constant would be, using a
650 * given Index and Context, if a constant of that name were defined.
652 * Returns folly::none if the constant isn't in the index.
654 folly::Optional<Type> lookup_constant(Context ctx,
655 SString cnsName) const;
658 * See if the named constant has a unique scalar definition, and
659 * return its value if so.
661 folly::Optional<Cell> lookup_persistent_constant(SString cnsName) const;
664 * Return true if the return value of the function might depend on arg.
666 bool func_depends_on_arg(const php::Func* func, int arg) const;
669 * If func is effect-free when called with args, and it returns a constant,
670 * return that constant; otherwise return TTop.
672 Type lookup_foldable_return_type(Context ctx,
673 const php::Func* func,
674 Type ctxType,
675 CompactVector<Type> args) const;
677 * Return the best known return type for a resolved function, in a
678 * context insensitive way. Returns TInitGen at worst.
680 Type lookup_return_type(Context, res::Func) const;
683 * Return the best known return type for a resolved function, given
684 * the supplied calling context. Returns TInitGen at worst.
686 * During analyze phases, this function may re-enter analyze in
687 * order to interpret the callee with these argument types.
689 Type lookup_return_type(Context caller,
690 const CompactVector<Type>& args,
691 const Type& context,
692 res::Func) const;
695 * Look up the return type for an unresolved function. The
696 * interpreter should not use this routine---it's for stats or debug
697 * dumps.
699 * Nothing may be writing to the index when this function is used,
700 * but concurrent readers are allowed.
702 Type lookup_return_type_raw(const php::Func*) const;
705 * Return the best known types of a closure's used variables (on
706 * entry to the closure). The function is the closure body.
708 * If move is true, the value will be moved out of the index. This
709 * should only be done at emit time. (note that the only other user
710 * of this info is analysis, which only uses it when processing the
711 * owning class, so its safe to kill after emitting the owning
712 * unit).
714 CompactVector<Type>
715 lookup_closure_use_vars(const php::Func*,
716 bool move = false) const;
719 * Return the availability of $this on entry to the provided method.
720 * If the Func provided is not a method of a class false is
721 * returned.
723 bool lookup_this_available(const php::Func*) const;
726 * Returns the parameter preparation kind (if known) for parameter
727 * `paramId' on the given resolved Func.
729 PrepKind lookup_param_prep(Context, res::Func, uint32_t paramId) const;
732 * Returns the control-flow insensitive inferred private instance
733 * property types for a Class. The Class doesn't need to be
734 * resolved, because private properties don't depend on the
735 * inheritance hierarchy.
737 * The Index tracks the largest types for private properties that
738 * are guaranteed to hold at any program point.
740 * If move is true, the value will be moved out of the index. This
741 * should only be done at emit time. (note that the only other user
742 * of this info is analysis, which only uses it when processing the
743 * owning class, so its safe to kill after emitting the owning
744 * unit).
746 PropState lookup_private_props(const php::Class*,
747 bool move = false) const;
750 * Returns the control-flow insensitive inferred private static
751 * property types for a Class. The class doesn't need to be
752 * resolved for the same reasons as for instance properties.
754 * The Index tracks the largest types for private static properties
755 * that are guaranteed to hold at any program point.
757 * If move is true, the value will be moved out of the index. This
758 * should only be done at emit time. (note that the only other user
759 * of this info is analysis, which only uses it when processing the
760 * owning class, so its safe to kill after emitting the owning
761 * unit).
763 PropState lookup_private_statics(const php::Class*,
764 bool move = false) const;
767 * Lookup the best known type for a public static property, with a given
768 * class and name.
770 * This function will always return TInitGen before refine_public_statics has
771 * been called, or if the AnalyzePublicStatics option is off.
773 Type lookup_public_static(Context ctx, const Type& cls,
774 const Type& name) const;
775 Type lookup_public_static(Context ctx, const php::Class*,
776 SString name) const;
779 * Lookup if initializing (which is a side-effect of several bytecodes) the
780 * given class might raise.
782 bool lookup_class_init_might_raise(Context, res::Class) const;
785 * Lookup if a public static property with the given class and name might be
786 * AttrLateInit.
788 bool lookup_public_static_maybe_late_init(const Type& cls,
789 const Type& name) const;
792 * Returns whether a public static property is known to be immutable. This
793 * is used to add AttrPersistent flags to static properties, and relies on
794 * AnalyzePublicStatics (without this flag it will always return false).
796 bool lookup_public_static_immutable(const php::Class*,
797 SString name) const;
800 * Lookup the best known type for a public (non-static) property. Since we
801 * don't do analysis on public properties, this just inferred from the
802 * property's type-hint (if enforced).
804 Type lookup_public_prop(const Type& cls, const Type& name) const;
805 Type lookup_public_prop(const php::Class* cls, SString name) const;
808 * We compute the interface vtables in a separate thread. It needs
809 * to be joined (in single threaded context) before calling
810 * lookup_iface_vtable_slot.
812 void join_iface_vtable_thread() const;
815 * Returns the computed vtable slot for the given class, if it's an interface
816 * that was given a vtable slot. No two interfaces implemented by the same
817 * class will share the same vtable slot. May return kInvalidSlot, if the
818 * given class isn't an interface or if it wasn't assigned a slot.
820 Slot lookup_iface_vtable_slot(const php::Class*) const;
823 * Return the DependencyContext for ctx.
825 DependencyContext dependency_context(const Context& ctx) const;
828 * Determine whether to use class-at-a-time, or function-at-a-time
829 * dependencies.
831 * Must be called in single-threaded context.
833 void use_class_dependencies(bool f);
836 * Initialize the initial types for public static properties. This should be
837 * done after rewriting initial property values, as that affects the types.
839 void init_public_static_prop_types();
842 * Refine the types of the class constants defined by an 86cinit,
843 * based on a round of analysis.
845 * No other threads should be using ctx.cls->constants or deps when
846 * this function is called.
848 * Merges the set of Contexts that depended on the constants defined
849 * by this 86cinit.
851 void refine_class_constants(
852 const Context& ctx,
853 const CompactVector<std::pair<size_t, TypedValue>>& resolved,
854 DependencyContextSet& deps);
857 * Refine the types of the constants defined by a function, based on
858 * a round of analysis.
860 * Constants not defined by a pseudomain are considered unknowable
862 * No other threads should be calling functions on this Index when
863 * this function is called.
865 * Merges the set of Contexts that depended on the constants defined
866 * by this php::Func into deps.
868 void refine_constants(const FuncAnalysisResult& fa,
869 DependencyContextSet& deps);
872 * Refine the return type for a function, based on a round of
873 * analysis.
875 * No other threads should be calling functions on this Index when
876 * this function is called.
878 * Merges the set of Contexts that depended on the return type of
879 * this php::Func into deps.
881 void refine_return_info(const FuncAnalysisResult& fa,
882 DependencyContextSet& deps);
885 * Refine the used var types for a closure, based on a round of
886 * analysis.
888 * No other threads should be calling functions on this Index when
889 * this function is called.
891 * Returns: true if the types have changed.
893 bool refine_closure_use_vars(const php::Class*,
894 const CompactVector<Type>&);
897 * Refine the private property types for a class, based on a round
898 * of analysis.
900 * No other threads should be calling functions on this Index when
901 * this function is called.
903 void refine_private_props(const php::Class* cls,
904 const PropState&);
907 * Refine the static private property types for a class, based on a
908 * round of analysis.
910 * No other threads should be calling functions on this Index when
911 * this function is called.
913 void refine_private_statics(const php::Class* cls,
914 const PropState&);
917 * Record in the index that the given set of public static property mutations
918 * has been found while analyzing the given function. During a round of
919 * analysis, the mutations are gathered from the analysis results for each
920 * function, recorded in the index, and then refine_public_statics is called
921 * to process the mutations and update the index.
923 * No other threads should be calling functions on this Index when this
924 * function is called.
926 void record_public_static_mutations(const php::Func& func,
927 PublicSPropMutations mutations);
931 * If we resolve the intial value of a public property, we need to
932 * tell the refine_public_statics phase about it, because the init
933 * value won't be included in the mutations any more.
935 * Note that we can't modify the initial value here, because other
936 * threads might be reading it (via loookup_public_static), so we
937 * set a flag to tell us to update it during the next
938 * refine_public_statics pass.
940 void update_static_prop_init_val(const php::Class* cls,
941 SString name) const;
943 * After a round of analysis with all the public static property mutations
944 * being recorded with record_public_static_mutations, the types can be
945 * reflected into the index for use during another type inference pass.
947 * No other threads should be calling functions on this Index when this
948 * function is called.
950 * Merges the set of Contexts that depended on a public static property whose
951 * type has changed.
953 void refine_public_statics(DependencyContextSet& deps);
956 * Refine whether the given class has properties with initial values which
957 * might violate their type-hints.
959 * No other threads should be calling functions on this Index when this
960 * function is called.
962 void refine_bad_initial_prop_values(const php::Class* cls,
963 bool value,
964 DependencyContextSet& deps);
967 * Identify the persistent classes, functions and typeAliases.
969 void mark_persistent_classes_and_functions(php::Program& program);
972 * Mark any properties in cls that definitely do not redeclare a property in
973 * the parent, which has an inequivalent type-hint.
975 void mark_no_bad_redeclare_props(php::Class& cls) const;
978 * Rewrite the initial values of any AttrSystemInitialValue properties to
979 * something more suitable for its type-hint, and add AttrNoImplicitNullable
980 * where appropriate.
982 * This must be done before any analysis is done, as the initial values
983 * affects the analysis.
985 void rewrite_default_initial_values(php::Program&) const;
988 * Return true if the resolved function supports async eager return.
990 folly::Optional<bool> supports_async_eager_return(res::Func rfunc) const;
993 * Return true if the resolved function is effect free.
995 bool is_effect_free(res::Func rfunc) const;
998 * Return true if there are any interceptable functions
1000 bool any_interceptable_functions() const;
1003 * Do any necessary fixups to a return type.
1005 * Note that eg for an async function it will map Type to
1006 * WaitH<Type>.
1008 void fixup_return_type(const php::Func*, Type&) const;
1011 * Return true if we know for sure that one php::Class must derive
1012 * from another at runtime, in all possible instantiations.
1014 bool must_be_derived_from(const php::Class*,
1015 const php::Class*) const;
1017 struct IndexData;
1018 private:
1019 Index(const Index&) = delete;
1020 Index& operator=(Index&&) = delete;
1022 private:
1023 friend struct PublicSPropMutations;
1025 template<class FuncRange>
1026 res::Func resolve_func_helper(const FuncRange&, SString) const;
1027 res::Func do_resolve(const php::Func*) const;
1028 bool could_be_related(const php::Class*,
1029 const php::Class*) const;
1031 template<bool getSuperType>
1032 Type get_type_for_constraint(Context,
1033 const TypeConstraint&,
1034 const Type&) const;
1036 struct ConstraintResolution;
1039 * Try to resolve name in the given context. Follows TypeAliases.
1041 ConstraintResolution resolve_class_or_type_alias(
1042 const Context& ctx, SString name, const Type& candidate) const;
1044 ConstraintResolution get_type_for_annotated_type(
1045 Context ctx, AnnotType annot, bool nullable,
1046 SString name, const Type& candidate) const;
1048 void init_return_type(const php::Func* func);
1050 ResolvedInfo<Either<SString,ClassInfo*>>
1051 resolve_type_name_internal(SString name) const;
1053 private:
1054 std::unique_ptr<IndexData> const m_data;
1057 //////////////////////////////////////////////////////////////////////
1060 * Used for collecting all mutations of public static property types.
1062 struct PublicSPropMutations {
1064 * This function must be called anywhere the interpreter does something that
1065 * could change the type of public static properties named `name' on classes
1066 * of type `cls' to `val'.
1068 * Note that if cls and name are both too generic this object will have to
1069 * give up all information it knows about any public static properties.
1071 void merge(const Index& index, Context ctx, const Type& cls,
1072 const Type& name, const Type& val);
1073 void merge(const Index& index, Context ctx, ClassInfo* cinfo,
1074 const Type& name, const Type& val);
1075 void merge(const Index& index, Context ctx, const php::Class& cls,
1076 const Type& name, const Type& val);
1078 private:
1079 friend struct Index;
1081 struct KnownKey {
1082 bool operator<(KnownKey o) const {
1083 if (cinfo != o.cinfo) return cinfo < o.cinfo;
1084 return prop < o.prop;
1087 ClassInfo* cinfo;
1088 SString prop;
1091 using UnknownMap = std::map<SString,Type>;
1092 using KnownMap = std::map<KnownKey,Type>;
1094 // Public static property mutations are actually rare, so defer allocating the
1095 // maps until we actually see one.
1096 struct Data {
1097 bool m_nothing_known{false};
1098 UnknownMap m_unknown;
1099 KnownMap m_known;
1101 std::unique_ptr<Data> m_data;
1104 //////////////////////////////////////////////////////////////////////
1108 #endif