Improve refineLocation a little
[hiphop-php.git] / hphp / hhbbc / index.h
blobbdb0d9c26c16ed27671d806936a0b9b3cf490432
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 PublicSPropIndexer;
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 Func;
57 struct Unit;
58 struct Program;
61 //////////////////////////////////////////////////////////////////////
64 * This module contains functions for building and querying an Index
65 * of data relating to "resolved" versions of the names in of a
66 * php::Program. It also records dependencies so it is possible to
67 * tell which parts of the program may be interested in new inferred
68 * information about other parts of the program.
70 * The main entry point here is the Index class. The Index is built
71 * after parse time, and then analysis can query it for information.
74 //////////////////////////////////////////////////////////////////////
77 * A DependencyContext encodes enough of the context to record a
78 * dependency - either a php::Func, or, if we're doing private
79 * property analysis and its a suitable class, a php::Class
81 using DependencyContext = Either<borrowed_ptr<php::Func>,
82 borrowed_ptr<const php::Class>>;
84 struct DependencyContextLess {
85 bool operator()(const DependencyContext& a,
86 const DependencyContext& b) const {
87 return a.toOpaque() < b.toOpaque();
91 struct DependencyContextHash {
92 size_t operator()(const DependencyContext& d) const {
93 return pointer_hash<void>{}(reinterpret_cast<void*>(d.toOpaque()));
97 using DependencyContextSet = std::unordered_set<DependencyContext,
98 DependencyContextHash>;
99 using ContextSet = std::unordered_set<Context, ContextHash>;
101 std::string show(Context);
103 using ConstantMap = std::unordered_map<SString, Cell>;
106 * State of properties on a class. Map from property name to its
107 * Type.
109 using PropState = std::map<LSString,Type>;
111 //////////////////////////////////////////////////////////////////////
113 // private types
114 struct ClassInfo;
116 //////////////////////////////////////////////////////////////////////
119 * References to "resolved" entities with information in the index are
120 * in the res:: namespace.
122 * These represent handles to program entities that may have variable
123 * amounts of information. For example, we may know the name of a
124 * class in a res::Class, but do not know for sure which php::Class
125 * struct is actually associated with it.
127 namespace res {
130 * A resolved runtime Class, for a particular php::Class.
132 * Provides various lookup tables that allow querying the Class'
133 * information.
135 struct Class {
137 * Returns whether two classes are definitely same at runtime. If
138 * this function returns false, they still *may* be the same at
139 * runtime.
141 bool same(const Class&) const;
144 * Returns true if this class is definitely going to be a subtype
145 * of `o' at runtime. If this function returns false, this may
146 * still be a subtype of `o' at runtime, it just may not be known.
147 * A typical example is with "non unique" classes.
149 bool subtypeOf(const Class& o) const;
152 * If this function return false, it is known that this class
153 * is in no subtype relationship with the argument Class 'o'.
154 * Returns true if this class could be a subtype of `o' at runtime.
155 * When true is returned the two classes may still be unrelated but it is
156 * not possible to tell. A typical example is with "non unique" classes.
158 bool couldBe(const Class& o) const;
161 * Returns the name of this class. Non-null guarantee.
163 SString name() const;
166 * Whether this class could possibly be an interface/interface or trait.
168 * True means it might be, false means it is not.
170 bool couldBeInterface() const;
171 bool couldBeInterfaceOrTrait() const;
174 * Returns whether this type has the no override attribute, that is, if it
175 * is a final class (explicitly marked by the user or known by the static
176 * analysis).
178 * When returning false the class is guaranteed to be final. When returning
179 * true the system cannot tell though the class may still be final.
181 bool couldBeOverriden() const;
184 * Whether this class (or its subtypes) could possibly have have
185 * certain magic methods.
187 bool couldHaveMagicGet() const;
190 * Whether this class (or its subtypes) could possibly have have
191 * a magic toBoolean() method.
193 bool couldHaveMagicBool() const;
196 * Whether this class could possibly have a derived class that is mocked.
197 * Including itself.
199 bool couldHaveMockedDerivedClass() const;
202 * Whether this class could possibly be mocked.
204 bool couldBeMocked() const;
207 * Returns the Class that is the first common ancestor between 'this' and 'o'.
208 * If there is no common ancestor folly::none is returned
210 folly::Optional<Class> commonAncestor(const Class& o) const;
213 * Returns the res::Class for this Class's parent if there is one,
214 * or nullptr.
216 folly::Optional<Class> parent() const;
219 * Returns true if we have a ClassInfo for this Class.
221 bool resolved() const {
222 return val.right() != nullptr;
226 * Returns the php::Class for this Class if there is one, or
227 * nullptr.
229 borrowed_ptr<const php::Class> cls() const;
231 private:
232 Class(borrowed_ptr<const Index>, Either<SString,borrowed_ptr<ClassInfo>>);
234 private:
235 friend std::string show(const Class&);
236 friend struct ::HPHP::HHBBC::Index;
237 friend struct ::HPHP::HHBBC::PublicSPropIndexer;
238 borrowed_ptr<const Index> index;
239 Either<SString,borrowed_ptr<ClassInfo>> val;
243 * This is an abstraction layer to represent possible runtime function
244 * resolutions.
246 * Internally, this may only know the name of the function (or method), or we
247 * may know exactly which source-code-level function it refers to, or we may
248 * only have ruled it down to one of a few functions in a class hierarchy. The
249 * interpreter can treat all these cases the same way using this.
251 struct Func {
253 * Returns whether two res::Funcs definitely mean the func at
254 * runtime.
256 * Note: this is potentially pessimistic for its use in ActRec state
257 * merging right now, but not incorrect.
259 bool same(const Func&) const;
262 * Returns the name of this function. Non-null guarantee.
264 SString name() const;
267 * If this resolved function represents exactly one php::Func, return it.
269 borrowed_ptr<const php::Func> exactFunc() const;
272 * Returns whether this resolved function could possibly be going through a
273 * magic call, in the magic way.
275 * That is, if was resolved as part of a direct call to an __call method,
276 * this will say true. If it was resolved as part as some normal method
277 * call, and we haven't proven that there's no way an __call dispatch could
278 * be involved, this will say false.
280 bool cantBeMagicCall() const;
283 * Returns whether this resolved function could possibly read or write to the
284 * caller's frame.
286 bool mightReadCallerFrame() const;
287 bool mightWriteCallerFrame() const;
288 bool mightAccessCallerFrame() const {
289 return mightReadCallerFrame() || mightWriteCallerFrame();
293 * Returns whether this resolved function is definitely safe to constant fold.
295 bool isFoldable() const;
298 * Returns whether this resolved function could possibly be skipped when
299 * looking for a caller's frame.
301 bool mightBeSkipFrame() const;
304 * Returns whether this resolved function might distinguish being called
305 * dynamically versus being called normally (IE, might raise a notice).
307 bool mightCareAboutDynCalls() const;
310 * Returns whether this resolved function might be a builtin.
312 bool mightBeBuiltin() const;
314 struct FuncInfo;
315 struct MethTabEntryPair;
316 struct FuncFamily;
318 private:
319 friend struct ::HPHP::HHBBC::Index;
320 struct FuncName {
321 bool operator==(FuncName o) const { return name == o.name; }
322 SString name;
324 struct MethodName {
325 bool operator==(MethodName o) const { return name == o.name; }
326 SString name;
328 using Rep = boost::variant< FuncName
329 , MethodName
330 , borrowed_ptr<FuncInfo>
331 , borrowed_ptr<const MethTabEntryPair>
332 , borrowed_ptr<FuncFamily>
335 private:
336 Func(borrowed_ptr<const Index>, Rep);
337 friend std::string show(const Func&);
339 private:
340 borrowed_ptr<const Index> index;
341 Rep val;
345 * Produce a trace-able string for a res::Func or res::Class.
347 std::string show(const Func&);
348 std::string show(const Class&);
352 //////////////////////////////////////////////////////////////////////
355 * This class encapsulates the known facts about the program, with a
356 * whole-program view.
358 * This structure contains unowned pointers into the php::Program it
359 * was created for. It should not out-live the Program.
361 * The const member functions of this class are thread safe for
362 * concurrent reads and writes. The non-const functions should be
363 * called in a single threaded context only (they are used during the
364 * "update" step in between whole program analysis rounds).
366 struct Index {
368 * Throwing a rebuild exception indicates that the index needs to
369 * be rebuilt.
371 * The exception should be passed to the Index constructor.
373 struct rebuild : std::exception {
374 explicit rebuild(std::vector<std::pair<SString, SString>> ca) :
375 class_aliases(std::move(ca)) {}
376 private:
377 friend struct Index;
378 std::vector<std::pair<SString, SString>> class_aliases;
382 * Create an Index for a php::Program. Performs some initial
383 * analysis of the program.
385 explicit Index(borrowed_ptr<php::Program>, rebuild* = nullptr);
388 * This class must not be destructed after its associated
389 * php::Program.
391 ~Index();
394 * The index operates in two modes: frozen, and unfrozen.
396 * Conceptually, the index is mutable and may acquire new
397 * information until it has been frozen, and once frozen, it retains
398 * the information it had at the point it was frozen.
400 * The reason this exists is because certain functions on the index
401 * may cause it to need to consult information in the bodies of
402 * functions other than the Context passed in. Specifically, if the
403 * interpreter tries to look up the return type for a callee in a
404 * given CallContext, the index may choose to recursively invoke
405 * type inference on that callee's function body to see if more
406 * precise information can be determined, unless it is frozen.
408 * This is fine until the final pass, because all bytecode is
409 * read-only at that stage. However, in the final pass, other
410 * threads might be optimizing a callee's bytecode and changing it,
411 * so we should not be reading from it to perform type inference
412 * concurrently. Freezing the index tells it it can't do that
413 * anymore.
415 * These are the functions to query and transition to frozen state.
417 bool frozen() const;
418 void freeze();
419 void thaw();
422 * Throw away data structures that won't be needed during the emit
423 * stage (or beyond).
425 void cleanup_for_emit(folly::Baton<>* done);
428 * The Index contains a Builder for an ArrayTypeTable.
430 * If we're creating assert types with options.InsertAssertions, we
431 * need to keep track of which array types exist in the whole
432 * program in order to include it in the repo.
434 std::unique_ptr<ArrayTypeTable::Builder>& array_table_builder() const;
437 * Find all the closures created inside the context of a given
438 * php::Class.
440 const CompactVector<borrowed_ptr<const php::Class>>*
441 lookup_closures(borrowed_ptr<const php::Class>) const;
444 * Find all the extra methods associated with a class from its
445 * traits.
447 const std::set<borrowed_ptr<php::Func>>*
448 lookup_extra_methods(borrowed_ptr<const php::Class>) const;
451 * Attempt to record a new alias in the index. May be called from
452 * multi-threaded contexts, so doesn't actually update the index
453 * (call update_class_aliases to do that). Returns false if it would
454 * violate any current uniqueness assumptions.
456 bool register_class_alias(SString orig, SString alias) const;
459 * Add any aliases that have been registered since the last call to
460 * update_class_aliases to the index. Must be called from a single
461 * threaded context.
463 void update_class_aliases();
466 * Try to find a res::Class for a given php::Class.
468 * Note, the returned class may or may not be *defined* at the
469 * program point you care about (it could be non-hoistable, even
470 * though it's unique, for example).
472 * Returns a name-only resolution if there are no legal
473 * instantiations of the class, or if there is more than one.
475 res::Class resolve_class(borrowed_ptr<const php::Class>) const;
478 * Try to resolve which class will be the class named `name' from a
479 * given context, if we can resolve it to a single class.
481 * Note, the returned class may or may not be *defined* at the
482 * program point you care about (it could be non-hoistable, even
483 * though it's unique, for example).
485 * Returns folly::none if we can't prove the supplied name must be a
486 * object type. (E.g. if there are type aliases.)
488 folly::Optional<res::Class> resolve_class(Context, SString name) const;
491 * Try to resolve self/parent types for the given context
493 folly::Optional<res::Class> selfCls(const Context& ctx) const;
494 folly::Optional<res::Class> parentCls(const Context& ctx) const;
496 struct ResolvedInfo {
497 AnnotType type;
498 bool nullable;
499 Either<SString,borrowed_ptr<ClassInfo>> value;
503 * Try to resolve name, looking through TypeAliases and enums.
505 ResolvedInfo resolve_type_name(SString name) const;
508 * Try to resolve name in the given context. Follows TypeAliases.
510 folly::Optional<Type> resolve_class_or_type_alias(
511 const Context& ctx, SString name, const Type& candidate) const;
514 * Resolve a closure class.
516 * Returns both a resolved Class, and the actual php::Class for the
517 * closure.
519 std::pair<res::Class,borrowed_ptr<php::Class>>
520 resolve_closure_class(Context ctx, int32_t idx) const;
523 * Return a resolved class for a builtin class.
525 * Pre: `name' must be the name of a class defined in a systemlib.
527 res::Class builtin_class(SString name) const;
530 * Try to resolve a function named `name' from a given context.
532 * Note, the returned function may or may not be defined at the
533 * program point (it could require a function autoload that might
534 * fail).
536 res::Func resolve_func(Context, SString name) const;
539 * Try to resolve a function using namespace-style fallback lookup.
541 * The name `name' is tried first, and `fallback' is used if this
542 * isn't found. Both names must already be namespace-normalized.
543 * If we don't know which will be called at runtime, both will be
544 * returned.
546 * Note: the returned function may or may not be defined at the
547 * program point (it could require a function autoload that might
548 * fail).
550 std::pair<res::Func, folly::Optional<res::Func>>
551 resolve_func_fallback(Context,
552 SString name,
553 SString fallback) const;
556 * Try to resolve a class method named `name' with a given Context
557 * and class type.
559 * Pre: clsType.subtypeOf(TCls)
561 res::Func resolve_method(Context, Type clsType, SString name) const;
564 * Try to resolve a class constructor for the supplied class type.
566 * Returns: folly::none if it can't at least figure out a func
567 * family for the call.
569 folly::Optional<res::Func>
570 resolve_ctor(Context, res::Class rcls, bool exact) const;
573 * Give the Type in our type system that matches an hhvm
574 * TypeConstraint, subject to the information in this Index.
576 * This function returns a subtype of Cell, although TypeConstraints
577 * at runtime can match reference parameters. The caller should
578 * make sure to handle that case.
580 * For soft constraints (@), this function returns Cell.
582 * For some non-soft constraints (such as "Stringish"), this
583 * function may return a Type that is a strict supertype of the
584 * constraint's type.
586 * If something is known about the type of the object against which
587 * the constraint will be checked, it can be passed in to help
588 * disambiguate certain constraints (useful because we don't support
589 * arbitrary unions, or intersection).
591 Type lookup_constraint(Context, const TypeConstraint&,
592 const Type& t = TTop) const;
595 * If this function returns true, it is safe to assume that Type t
596 * will always satisfy TypeConstraint tc at run time.
598 bool satisfies_constraint(Context, const Type& t,
599 const TypeConstraint& tc) const;
602 * Lookup what the best known Type for a class constant would be,
603 * using a given Index and Context, if a class of that name were
604 * loaded.
606 Type lookup_class_constant(Context, res::Class, SString cns) const;
609 * Lookup what the best known Type for a constant would be, using a
610 * given Index and Context, if a constant of that name were defined.
612 * If fallbackName is provided, and known to be defined, and cnsName
613 * is known not to be defined, and HardConstProp is set, resolve
614 * fallbackName instead.
616 * Returns folly::none if the constant isn't in the index.
618 folly::Optional<Type> lookup_constant(Context ctx,
619 SString cnsName,
620 SString fallbackName = nullptr) const;
623 * See if the named constant has a unique scalar definition, and
624 * return its value if so.
626 folly::Optional<Cell> lookup_persistent_constant(SString cnsName) const;
629 * If func is effect-free when called with args, and it returns a constant,
630 * return that constant; otherwise return TTop.
632 Type lookup_foldable_return_type(Context ctx,
633 borrowed_ptr<const php::Func> func,
634 std::vector<Type> args) const;
636 * Return the best known return type for a resolved function, in a
637 * context insensitive way. Returns TInitGen at worst.
639 Type lookup_return_type(Context, res::Func) const;
642 * Return the best known return type for a resolved function, given
643 * the supplied calling context. Returns TInitGen at worst.
645 * During analyze phases, this function may re-enter analyze in
646 * order to interpret the callee with these argument types.
648 Type lookup_return_type(CallContext, res::Func) const;
651 * Look up the return type for an unresolved function. The
652 * interpreter should not use this routine---it's for stats or debug
653 * dumps.
655 * Nothing may be writing to the index when this function is used,
656 * but concurrent readers are allowed.
658 Type lookup_return_type_raw(borrowed_ptr<const php::Func>) const;
661 * As lookup_return_type_raw, but also clean out the FuncInfo struct.
662 * For use during emit, to keep memory usage down.
664 Type lookup_return_type_and_clear(borrowed_ptr<const php::Func>) const;
667 * Return the best known types of a closure's used variables (on
668 * entry to the closure). The function is the closure body.
670 * If move is true, the value will be moved out of the index. This
671 * should only be done at emit time.
673 std::vector<Type>
674 lookup_closure_use_vars(borrowed_ptr<const php::Func>,
675 bool move = false) const;
677 CompactVector<Type>
678 lookup_local_static_types(borrowed_ptr<const php::Func> f) const;
681 * Return the availability of $this on entry to the provided method.
682 * If the Func provided is not a method of a class false is
683 * returned.
685 bool lookup_this_available(borrowed_ptr<const php::Func>) const;
688 * Returns the parameter preparation kind (if known) for parameter
689 * `paramId' on the given resolved Func.
691 PrepKind lookup_param_prep(Context, res::Func, uint32_t paramId) const;
694 * Returns the control-flow insensitive inferred private instance
695 * property types for a Class. The Class doesn't need to be
696 * resolved, because private properties don't depend on the
697 * inheritance hierarchy.
699 * The Index tracks the largest types for private properties that
700 * are guaranteed to hold at any program point.
702 * If move is true, the value will be moved out of the index. This
703 * should only be done at emit time.
705 PropState lookup_private_props(borrowed_ptr<const php::Class>,
706 bool move = false) const;
709 * Returns the control-flow insensitive inferred private static
710 * property types for a Class. The class doesn't need to be
711 * resolved for the same reasons as for instance properties.
713 * The Index tracks the largest types for private static properties
714 * that are guaranteed to hold at any program point.
716 * If move is true, the value will be moved out of the index. This
717 * should only be done at emit time.
719 PropState lookup_private_statics(borrowed_ptr<const php::Class>,
720 bool move = false) const;
723 * Lookup the best known type for a public static property, with a given
724 * class and name.
726 * This function will always return TInitGen before refine_public_statics has
727 * been called, or if the AnalyzePublicStatics option is off.
729 Type lookup_public_static(const Type& cls, const Type& name) const;
730 Type lookup_public_static(borrowed_ptr<const php::Class>, SString name) const;
733 * If we resolve a public static initializer to a constant, and eliminate the
734 * 86pinit, we need to update the initializer in the index.
736 * Note that this is called from code that runs in parallel, and
737 * consequently isn't normally allowed to modify the index. Its safe
738 * in this case, because for any given property there can only be
739 * one InitProp which sets it, and all we do is modify an existing
740 * element of a map.
742 void fixup_public_static(borrowed_ptr<const php::Class>, SString name,
743 const Type& ty) const;
745 * Returns whether a public static property is known to be immutable. This
746 * is used to add AttrPersistent flags to static properties, and relies on
747 * AnalyzePublicStatics (without this flag it will always return false).
749 bool lookup_public_static_immutable(borrowed_ptr<const php::Class>,
750 SString name) const;
753 * Returns the computed vtable slot for the given class, if it's an interface
754 * that was given a vtable slot. No two interfaces implemented by the same
755 * class will share the same vtable slot. May return kInvalidSlot, if the
756 * given class isn't an interface or if it wasn't assigned a slot.
758 Slot lookup_iface_vtable_slot(borrowed_ptr<const php::Class>) const;
761 * Return the DependencyContext for ctx.
763 DependencyContext dependency_context(const Context& ctx) const;
766 * Determine whether to use class-at-a-time, or function-at-a-time
767 * dependencies.
769 * Must be called in single-threaded context.
771 void use_class_dependencies(bool f);
774 * Refine the types of the class constants defined by an 86cinit,
775 * based on a round of analysis.
777 * No other threads should be using ctx.cls->constants or deps when
778 * this function is called.
780 * Merges the set of Contexts that depended on the constants defined
781 * by this 86cinit.
783 void refine_class_constants(
784 const Context& ctx,
785 const CompactVector<std::pair<size_t, TypedValue>>& resolved,
786 DependencyContextSet& deps);
789 * Refine the types of the constants defined by a function, based on
790 * a round of analysis.
792 * Constants not defined by a pseudomain are considered unknowable
794 * No other threads should be calling functions on this Index when
795 * this function is called.
797 * Merges the set of Contexts that depended on the constants defined
798 * by this php::Func into deps.
800 void refine_constants(const FuncAnalysisResult& fa,
801 DependencyContextSet& deps);
804 * Refine the types of the local statics owned by the function.
806 void refine_local_static_types(borrowed_ptr<const php::Func> func,
807 const CompactVector<Type>& localStaticTypes);
810 * Refine the effectFree flag for func.
812 void refine_effect_free(borrowed_ptr<const php::Func> func, bool flag);
815 * Refine the return type for a function, based on a round of
816 * analysis.
818 * No other threads should be calling functions on this Index when
819 * this function is called.
821 * Merges the set of Contexts that depended on the return type of
822 * this php::Func into deps.
824 void refine_return_type(borrowed_ptr<const php::Func>, Type,
825 DependencyContextSet& deps);
828 * Refine the used var types for a closure, based on a round of
829 * analysis.
831 * No other threads should be calling functions on this Index when
832 * this function is called.
834 * Returns: true if the types have changed.
836 bool refine_closure_use_vars(borrowed_ptr<const php::Class>,
837 const std::vector<Type>&);
840 * Refine the private property types for a class, based on a round
841 * of analysis.
843 * No other threads should be calling functions on this Index when
844 * this function is called.
846 void refine_private_props(borrowed_ptr<const php::Class> cls,
847 const PropState&);
850 * Refine the static private property types for a class, based on a
851 * round of analysis.
853 * No other threads should be calling functions on this Index when
854 * this function is called.
856 void refine_private_statics(borrowed_ptr<const php::Class> cls,
857 const PropState&);
860 * After a whole program pass using PublicSPropIndexer, the types can be
861 * reflected into the index for use during another type inference pass.
863 * No other threads should be calling functions on this Index or on the
864 * provided PublicSPropIndexer when this function is called.
866 void refine_public_statics(const PublicSPropIndexer&);
869 * Identify the persistent classes, functions and typeAliases.
871 void mark_persistent_classes_and_functions(php::Program& program);
874 * Return true if the resolved function is an async
875 * function.
877 bool is_async_func(res::Func rfunc) const;
880 * Return true if the resolved function is effect free.
882 bool is_effect_free(res::Func rfunc) const;
885 * Return true if there are any interceptable functions
887 bool any_interceptable_functions() const;
890 * Do any necessary fixups to a return type.
892 * Note that eg for an async function it will map Type to
893 * WaitH<Type>.
895 void fixup_return_type(borrowed_ptr<const php::Func>, Type&) const;
898 * Return true if we know for sure that one php::Class must derive
899 * from another at runtime, in all possible instantiations.
901 bool must_be_derived_from(borrowed_ptr<const php::Class>,
902 borrowed_ptr<const php::Class>) const;
904 struct IndexData;
905 private:
906 Index(const Index&) = delete;
907 Index& operator=(Index&&) = delete;
909 private:
910 friend struct PublicSPropIndexer;
911 template<class FuncRange>
912 res::Func resolve_func_helper(const FuncRange&, SString) const;
913 res::Func do_resolve(borrowed_ptr<const php::Func>) const;
914 bool could_be_related(borrowed_ptr<const php::Class>,
915 borrowed_ptr<const php::Class>) const;
917 template<bool getSuperType>
918 Type get_type_for_constraint(Context,
919 const TypeConstraint&,
920 const Type&) const;
921 folly::Optional<Type> get_type_for_annotated_type(
922 Context ctx, AnnotType annot, bool nullable,
923 SString name, const Type& candidate) const;
925 void init_return_type(borrowed_ptr<const php::Func> func);
927 private:
928 std::unique_ptr<IndexData> const m_data;
931 //////////////////////////////////////////////////////////////////////
934 * Indexer object used for collecting information about public static property
935 * types. See analyze_public_statics in whole-program.cpp for details about
936 * how it is used.
938 struct PublicSPropIndexer {
939 explicit PublicSPropIndexer(borrowed_ptr<const Index> index)
940 : m_index(index)
944 * Called by the interpreter during analyze_func_collect when a
945 * PublicSPropIndexer is active. This function must be called anywhere the
946 * interpreter does something that could change the type of public static
947 * properties named `name' on classes of type `cls' to `val'.
949 * Note that if cls and name are both too generic this object will have to
950 * give up all information it knows about any public static properties.
952 * This routine may be safely called concurrently by multiple analysis
953 * threads.
955 void merge(Context ctx, const Type& cls, const Type& name, const Type& val);
956 void merge(Context ctx, ClassInfo* cinfo,
957 const Type& name, const Type& val);
958 void merge(Context ctx, const php::Class& cls,
959 const Type& name, const Type& val);
961 private:
962 friend struct Index;
964 struct KnownKey {
965 bool operator==(KnownKey o) const {
966 return cinfo == o.cinfo && prop == o.prop;
969 friend size_t tbb_hasher(KnownKey k) {
970 return folly::hash::hash_combine(k.cinfo, k.prop);
973 borrowed_ptr<ClassInfo> cinfo;
974 SString prop;
977 using UnknownMap = tbb::concurrent_hash_map<SString,Type>;
978 using KnownMap = tbb::concurrent_hash_map<KnownKey,Type>;
980 private:
981 borrowed_ptr<const Index> m_index;
982 std::atomic<bool> m_everything_bad{false};
983 UnknownMap m_unknown;
984 KnownMap m_known;
987 //////////////////////////////////////////////////////////////////////
991 #endif