From 37c8a491769b4e5a4e750ab6665b0975a72556be Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 19 Oct 2026 16:42:15 +0200 Subject: [PATCH 01/13] Share the plain ObjectTypes native code creates per container MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pt_object_type_new() without a subtracted type or a handed-in class reflection hands back one ObjectType per class name: the value is the same, and the instance's caches (ancestors, parent, interfaces, the lazily resolved class reflection, the method cache) are computed once instead of per instance. The reflection belongs to the container, so the table is dropped with ObjectType::resetCaches(), which ContainerFactory calls for every new container, and at request shutdown. 652k ObjectType creations per single-process self-analysis were the largest group of type objects in the allocation census. Measured −0.92% instructions (sd 0.06%, n=4), user CPU −0.71% (noisy), identical output, peak memory unchanged. Leaf types (MixedType, NullType, ...) are not interned: that was measured at ~0 before and removed (#6355). Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01MMNnG2Zo7wgvSZCzjdk17X --- turbo-ext/src/ObjectType.cpp | 39 +++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/turbo-ext/src/ObjectType.cpp b/turbo-ext/src/ObjectType.cpp index 7202f46f893..b1d908490df 100644 --- a/turbo-ext/src/ObjectType.cpp +++ b/turbo-ext/src/ObjectType.cpp @@ -156,9 +156,27 @@ static zval *pt_ot_enum_cases() { return pt_ot_static(PT_OT_STATIC_ENUM_CASES); static zval *pt_ot_description_cache_order() { return pt_ot_static(PT_OT_STATIC_DESCRIPTION_CACHE_ORDER); } static zval *pt_ot_last_touched_description() { return pt_ot_static(PT_OT_STATIC_LAST_TOUCHED_DESCRIPTION); } +/* The plain ObjectTypes (no subtracted type, no class reflection handed + * in) native code creates, one per class name: the value is the same, and + * the instance's own caches (ancestors, parent, interfaces, the resolved + * class reflection) are then computed once. A lazily resolved class + * reflection belongs to the container, so the table is dropped with the + * container's caches (resetCaches()) and at the end of the request. */ +static HashTable *pt_ot_interned = nullptr; + +static void pt_ot_interned_clear() +{ + if (pt_ot_interned == nullptr) return; + HashTable *interned = pt_ot_interned; + pt_ot_interned = nullptr; + zend_hash_destroy(interned); + FREE_HASHTABLE(interned); +} + /* resetCaches(): every cache back to [], the LRU and its memo to null */ static void pt_ot_statics_reset() { + pt_ot_interned_clear(); for (int i = PT_OT_STATIC_SUPER_TYPES; i <= PT_OT_STATIC_ENUM_CASES; i++) { zv::Ref(pt_ot_static((pt_ot_static_kind) i)).assign(zv::Val(zv::Arr::empty())); } @@ -174,6 +192,7 @@ void pt_object_type_rinit() void pt_object_type_rshutdown() { pt_ot_statics_ce = nullptr; + pt_ot_interned_clear(); } /* $cache[$key] — the nested array, created when asked for; NULL when absent */ @@ -3258,7 +3277,25 @@ using phpstanturbo::ObjectType; bool pt_object_type_new(zval *out, zend_string *className, zval *subtractedType, zval *classReflection) { - return pt_val_into(ObjectType::create(className, subtractedType, classReflection), out); + if ((subtractedType != NULL && Z_TYPE_P(subtractedType) != IS_NULL) || (classReflection != NULL && Z_TYPE_P(classReflection) != IS_NULL)) { + return pt_val_into(ObjectType::create(className, subtractedType, classReflection), out); + } + if (pt_ot_interned != nullptr) { + zval *interned = zend_hash_find(pt_ot_interned, className); + if (interned != NULL) { + ZVAL_COPY(out, interned); + return true; + } + } + zv::Val created = ObjectType::create(className); + if (UNEXPECTED(created.isUndef())) return false; + if (pt_ot_interned == nullptr) { + ALLOC_HASHTABLE(pt_ot_interned); + zend_hash_init(pt_ot_interned, 64, NULL, ZVAL_PTR_DTOR, 0); + } + Z_ADDREF_P(created.raw()); + zend_hash_add_new(pt_ot_interned, className, created.raw()); + return pt_val_into(std::move(created), out); } zend_string *pt_object_type_class_name(zend_object *object) { return ObjectType::classNameOf(object); } From 5b2f9a4a610489fe56588c832460c0c276551a44 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 19 Oct 2026 20:44:11 +0200 Subject: [PATCH 02/13] Build a traversal's bound callables once and hand them to types resolved TypeTraverser built a fresh [$this, 'mapInternal'] / [$this, 'traverseInternal'] array for every traversed type, and each native Type::traverse() resolved it by name through zend_fcall_info_init(). The traversals in progress now keep their two callables on a small stack, released when map() returns, and the traverse op fills the fci/fcc of such an array directly. A callable kept or called after its map() returned is built and resolved as before. Instructions retired on self-analysis: -1.01% (3 ABBA pairs), identical analysis output. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01MMNnG2Zo7wgvSZCzjdk17X --- turbo-ext/src/Core.cpp | 1 + turbo-ext/src/TypeOps.h | 5 ++ turbo-ext/src/TypeTraverser.cpp | 125 ++++++++++++++++++++++++++++++-- turbo-ext/src/support.h | 2 + 4 files changed, 128 insertions(+), 5 deletions(-) diff --git a/turbo-ext/src/Core.cpp b/turbo-ext/src/Core.cpp index 88dc9ad7d01..2266e0a3b7f 100644 --- a/turbo-ext/src/Core.cpp +++ b/turbo-ext/src/Core.cpp @@ -113,6 +113,7 @@ PT_CORE_API void pt_core_rshutdown() pt_accepts_result_rshutdown(); pt_support_rshutdown(); pt_object_type_rshutdown(); + pt_type_traverser_rshutdown(); pt_static_type_factory_rshutdown(); pt_engine_rshutdown(); } diff --git a/turbo-ext/src/TypeOps.h b/turbo-ext/src/TypeOps.h index d88663b50e9..5bc8f58d0ee 100644 --- a/turbo-ext/src/TypeOps.h +++ b/turbo-ext/src/TypeOps.h @@ -341,8 +341,13 @@ static zend_always_inline zv::Val pt_op_string(const char *s) /* the Z_PARAM_FUNC parse of a traverse() callback: false = not callable — * the caller then takes the engine path, whose zpp raises the TypeError */ +/* TypeTraverser.cpp: fci/fcc of a TypeTraverser's own bound callable + * without resolving it by name; false for any other value */ +bool pt_type_traverser_bound_fcc(zval *callable, zend_fcall_info &fci, zend_fcall_info_cache &fcc); + static zend_always_inline bool pt_op_parse_callable(zval *cb, zend_fcall_info &fci, zend_fcall_info_cache &fcc) { + if (Z_TYPE_P(cb) == IS_ARRAY && pt_type_traverser_bound_fcc(cb, fci, fcc)) return true; if (UNEXPECTED(zend_fcall_info_init(cb, 0, &fci, &fcc, NULL, NULL) != SUCCESS)) return false; /* as Z_PARAM_FUNC does: a trampoline is refetched by the call */ zend_release_fcall_info_cache(&fcc); diff --git a/turbo-ext/src/TypeTraverser.cpp b/turbo-ext/src/TypeTraverser.cpp index 9c81d418f80..27b402a5020 100644 --- a/turbo-ext/src/TypeTraverser.cpp +++ b/turbo-ext/src/TypeTraverser.cpp @@ -24,6 +24,65 @@ zend_class_entry *pt_ce_type_traverser = NULL; static zend_string *pt_tt_str_map_internal = NULL; static zend_string *pt_tt_str_traverse_internal = NULL; +/* The traversals in progress, innermost last, each with its two bound + * callables — [$this, 'mapInternal'] and [$this, 'traverseInternal'] — + * built on first use instead of once per traversed type, and released when + * its map() returns (each holds the instance). A traversal nested deeper + * than the stack, or a callable called after its map() returned, builds + * fresh ones as before. */ +#define PT_TT_ACTIVE_LIMIT 64 + +struct ActiveTraversal +{ + zend_object *traverser; + zval mapCallable; + zval traverseCallable; +}; + +static ActiveTraversal pt_tt_active[PT_TT_ACTIVE_LIMIT]; +static uint32_t pt_tt_active_depth = 0; + +/* the cache slots of a traversal in progress, NULL when there is none */ +static ActiveTraversal *ttActive(zend_object *traverser) +{ + for (uint32_t i = pt_tt_active_depth; i > 0 && i <= PT_TT_ACTIVE_LIMIT; i--) { + if (pt_tt_active[i - 1].traverser == traverser) return &pt_tt_active[i - 1]; + } + return NULL; +} + +/* marks the traversal of one map() call as in progress for its lifetime */ +class ActiveTraversalScope +{ +public: + explicit ActiveTraversalScope(zend_object *traverser) + { + if (pt_tt_active_depth < PT_TT_ACTIVE_LIMIT) { + ActiveTraversal &entry = pt_tt_active[pt_tt_active_depth]; + entry.traverser = traverser; + ZVAL_UNDEF(&entry.mapCallable); + ZVAL_UNDEF(&entry.traverseCallable); + } + pt_tt_active_depth++; + } + + ~ActiveTraversalScope() + { + pt_tt_active_depth--; + if (pt_tt_active_depth < PT_TT_ACTIVE_LIMIT) { + ActiveTraversal &entry = pt_tt_active[pt_tt_active_depth]; + entry.traverser = NULL; + zval_ptr_dtor(&entry.mapCallable); + zval_ptr_dtor(&entry.traverseCallable); + ZVAL_UNDEF(&entry.mapCallable); + ZVAL_UNDEF(&entry.traverseCallable); + } + } + + ActiveTraversalScope(const ActiveTraversalScope &) = delete; + ActiveTraversalScope &operator=(const ActiveTraversalScope &) = delete; +}; + namespace phpstanturbo { /* Mirrors PHPStan\Type\TypeTraverser. State lives in the PHP object's $cb. */ @@ -42,6 +101,7 @@ class TypeTraverser zv::Val holder = zv::Val::adopt(object); TypeTraverser traverser(Z_OBJ(object)); traverser.construct(cb); + ActiveTraversalScope active(Z_OBJ(object)); return traverser.mapInternal(type); } @@ -56,6 +116,7 @@ class TypeTraverser zval *memo = OBJ_PROP_NUM(Z_OBJ(object), slots::memo); zval_ptr_dtor(memo); ZVAL_EMPTY_ARRAY(memo); + ActiveTraversalScope active(Z_OBJ(object)); return traverser.mapInternal(type); } @@ -110,7 +171,7 @@ class TypeTraverser zv::Val callCallback(zval *type) const { zval *cb = OBJ_PROP_NUM(self, slots::cb); - zv::Val traverse = boundCallable(pt_tt_str_traverse_internal); + zv::Val traverse = boundCallable(false, pt_tt_str_traverse_internal); zv::Args args{type, traverse.raw()}; bool isTraverserCallable; if (UNEXPECTED(!pt_type_instanceof(cb, PT_CLASS_TYPE_TRAVERSER_CALLABLE, isTraverserCallable))) return zv::Val(); @@ -132,16 +193,19 @@ class TypeTraverser /* $type->traverse([$this, 'mapInternal']); UNDEF = pending exception */ zv::Val traverseInternal(zval *type) const { - zv::Val map = boundCallable(pt_tt_str_map_internal); + zv::Val map = boundCallable(true, pt_tt_str_map_internal); return pt_type_op(Z_OBJ_P(type), PT_OP_TRAVERSE, 1, map.raw()); } private: zend_object *self; - /* [$this, ''] */ - zv::Val boundCallable(zend_string *method) const + /* [$this, ''], kept for the traversal in progress */ + zv::Val boundCallable(bool map, zend_string *method) const { + ActiveTraversal *active = ttActive(self); + zval *cache = active == NULL ? NULL : (map ? &active->mapCallable : &active->traverseCallable); + if (cache != NULL && Z_TYPE_P(cache) != IS_UNDEF) return zv::Val::copyOf(zv::Ref(cache)); zv::Arr callable = zv::Arr::create(2); zval selfZv; ZVAL_OBJ(&selfZv, self); @@ -149,7 +213,9 @@ class TypeTraverser zval methodZv; ZVAL_INTERNED_STR(&methodZv, method); callable.push(zv::Ref(&methodZv)); - return zv::Val(std::move(callable)); + zv::Val built(std::move(callable)); + if (cache != NULL) ZVAL_COPY(cache, built.raw()); + return built; } }; @@ -159,6 +225,20 @@ using phpstanturbo::TypeTraverser; /* {{{ exported helpers */ +void pt_type_traverser_rshutdown() +{ + /* a bailout skipped the scopes of the traversals it interrupted */ + uint32_t depth = pt_tt_active_depth < PT_TT_ACTIVE_LIMIT ? pt_tt_active_depth : PT_TT_ACTIVE_LIMIT; + for (uint32_t i = 0; i < depth; i++) { + pt_tt_active[i].traverser = NULL; + zval_ptr_dtor(&pt_tt_active[i].mapCallable); + zval_ptr_dtor(&pt_tt_active[i].traverseCallable); + ZVAL_UNDEF(&pt_tt_active[i].mapCallable); + ZVAL_UNDEF(&pt_tt_active[i].traverseCallable); + } + pt_tt_active_depth = 0; +} + bool pt_type_traverser_map(zval *out, zval *type, zval *cb) { zv::Val result = TypeTraverser::map(type, cb); @@ -210,6 +290,41 @@ static void ZEND_FASTCALL ttTraverseInternal(INTERNAL_FUNCTION_PARAMETERS) PT_RETURN_VAL(TypeTraverser(Z_OBJ_P(ZEND_THIS)).traverseInternal(type)); } +bool pt_type_traverser_bound_fcc(zval *callable, zend_fcall_info &fci, zend_fcall_info_cache &fcc) +{ + HashTable *ht = Z_ARRVAL_P(callable); + if (!HT_IS_PACKED(ht) || zend_hash_num_elements(ht) != 2 || ht->nNumUsed != 2) return false; + zval *object = zend_hash_index_find(ht, 0); + zval *method = zend_hash_index_find(ht, 1); + if (Z_TYPE_P(object) != IS_OBJECT || Z_OBJCE_P(object) != pt_ce_type_traverser || Z_TYPE_P(method) != IS_STRING) return false; + /* only the arrays boundCallable() builds: the interned names by identity */ + static zend_class_entry *cachedCe = NULL; + static zend_function *mapInternal = NULL; + static zend_function *traverseInternal = NULL; + if (cachedCe != pt_ce_type_traverser) { + mapInternal = (zend_function *) zend_hash_str_find_ptr(&PT_CE(pt_ce_type_traverser, function_table), "mapinternal", sizeof("mapinternal") - 1); + traverseInternal = (zend_function *) zend_hash_str_find_ptr(&PT_CE(pt_ce_type_traverser, function_table), "traverseinternal", sizeof("traverseinternal") - 1); + cachedCe = pt_ce_type_traverser; + } + zend_function *fn = Z_STR_P(method) == pt_tt_str_map_internal ? mapInternal + : (Z_STR_P(method) == pt_tt_str_traverse_internal ? traverseInternal : NULL); + if (fn == NULL) return false; + /* what zend_fcall_info_init() fills for the resolved [$object, 'method'] */ + fci.size = sizeof(fci); + ZVAL_COPY_VALUE(&fci.function_name, callable); + fci.object = Z_OBJ_P(object); + fci.retval = NULL; + fci.params = NULL; + fci.param_count = 0; + fci.named_params = NULL; + fcc.function_handler = fn; + fcc.calling_scope = pt_ce_type_traverser; + fcc.called_scope = pt_ce_type_traverser; + fcc.object = Z_OBJ_P(object); + fcc.closure = NULL; + return true; +} + zif_handler pt_type_traverser_map_internal_handler() { return ttMapInternal; diff --git a/turbo-ext/src/support.h b/turbo-ext/src/support.h index 2a07789bc6a..24d4252f56a 100644 --- a/turbo-ext/src/support.h +++ b/turbo-ext/src/support.h @@ -1011,6 +1011,8 @@ extern zend_class_entry *pt_ce_generic_object_type; extern zend_class_entry *pt_ce_enum_case_object_type; void pt_object_type_rinit(); void pt_object_type_rshutdown(); +/* TypeTraverser.cpp: the traversals a bailout left in progress */ +void pt_type_traverser_rshutdown(); /* new ObjectType($className, $subtractedType, $classReflection) / new * GenericObjectType($mainType, $types, $subtractedType, $classReflection, * $variances) / new EnumCaseObjectType($className, $enumCaseName, From 8f5926f169ac9d5ef35505bd3db52ff5c3203b75 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 20 Oct 2026 14:56:06 +0200 Subject: [PATCH 03/13] Stop buffering possible cycle roots while the collector is off bin/phpstan disables the garbage collector, but the engine still records each array and object whose refcount drops to non-zero in the root buffer, which then only grows, and every free of a buffered value searches it to remove the entry (gc_remove_compressed once past 512K roots). Activation protects the buffer when the collector is off, so nothing is recorded. -0.58% instructions, -10MB peak memory on the single-process benchmark. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01MMNnG2Zo7wgvSZCzjdk17X --- turbo-ext/src/main.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/turbo-ext/src/main.cpp b/turbo-ext/src/main.cpp index b12070c7271..bd8ac04380d 100644 --- a/turbo-ext/src/main.cpp +++ b/turbo-ext/src/main.cpp @@ -55,6 +55,13 @@ static void ZEND_FASTCALL runtimeActivateShadowing(INTERNAL_FUNCTION_PARAMETERS) if (!zp::parse>(execute_data, twinFiles, prefix)) RETURN_THROWS(); if (!pt_shadow_activate(twinFiles, prefix)) RETURN_THROWS(); + + /* bin/phpstan runs with gc_disable(), yet the engine still records + * every decremented array and object as a possible cycle root in a + * buffer that only grows (nothing collects it), and every free then + * removes its entry from that buffer again. Protecting the buffer stops + * the recording; no collection would ever have read it. */ + if (!gc_enabled()) gc_protect(true); } /* PHPStanTurbo\Runtime::isShadowing() — whether activateShadowing() ran */ From 07fe1761b2c6d0b7512565a7bafc08437bcd9ec7 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 20 Oct 2026 15:51:58 +0200 Subject: [PATCH 04/13] Look up node class infos by class entry before the by-name table Every printed, keyed or attribute-read node asked the by-name table, which hashes and compares the class name; a direct-mapped table by class entry in front of it answers them with one load. -0.59% instructions (median) on the single-process benchmark. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01MMNnG2Zo7wgvSZCzjdk17X --- turbo-ext/src/support.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/turbo-ext/src/support.cpp b/turbo-ext/src/support.cpp index f3eaca418cd..987f10efc90 100644 --- a/turbo-ext/src/support.cpp +++ b/turbo-ext/src/support.cpp @@ -711,7 +711,29 @@ int32_t pt_instance_prop_offset(zend_class_entry *ce, const char *name, size_t l return (int32_t) info->offset; } +/* the infos by class entry in front of the by-name table: every printed, + * keyed or attribute-read node asks, over a few hundred node classes */ +static constexpr uint32_t PT_NODE_CLASS_INFO_SLOTS_LIMIT = 256; +struct pt_node_class_info_slot +{ + const zend_class_entry *ce; + uint32_t generation; + pt_node_class_info *info; +}; +static pt_node_class_info_slot pt_node_class_info_slots[PT_NODE_CLASS_INFO_SLOTS_LIMIT]; + +static pt_node_class_info *pt_get_node_class_info_slow(zend_class_entry *ce); + pt_node_class_info *pt_get_node_class_info(zend_class_entry *ce) +{ + pt_node_class_info_slot &slot = pt_node_class_info_slots[(((uintptr_t) ce) >> 4) & (PT_NODE_CLASS_INFO_SLOTS_LIMIT - 1)]; + if (EXPECTED(slot.ce == ce && slot.generation == pt_engine_generation)) return slot.info; + pt_node_class_info *info = pt_get_node_class_info_slow(ce); + if (EXPECTED(info != NULL)) slot = { ce, pt_engine_generation, info }; + return info; +} + +static pt_node_class_info *pt_get_node_class_info_slow(zend_class_entry *ce) { pt_node_class_info *info; zend_class_entry *variable_ce; From bf0af31c621471bbeb1a5f03996a42573bf922f0 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 20 Oct 2026 15:51:58 +0200 Subject: [PATCH 05/13] Reuse TypeTraverser instances across traversals map() created an instance per traversal (1.6M per self-analysis subset) and freed it when the traversal ended. An instance nothing outlived the traversal with is now reset to the constructor's state and handed to the next map(). -0.20% instructions on the single-process benchmark. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01MMNnG2Zo7wgvSZCzjdk17X --- turbo-ext/src/TypeTraverser.cpp | 81 +++++++++++++++++++++++++++------ 1 file changed, 67 insertions(+), 14 deletions(-) diff --git a/turbo-ext/src/TypeTraverser.cpp b/turbo-ext/src/TypeTraverser.cpp index 27b402a5020..74c66ea00dc 100644 --- a/turbo-ext/src/TypeTraverser.cpp +++ b/turbo-ext/src/TypeTraverser.cpp @@ -3,7 +3,8 @@ * * When the extension is active, PHPStan\Type\TypeTraverser is this class, * declared under that name at activation (final, like the twin). map() - * builds one instance per traversal; the callback receives the instance's + * uses one instance per traversal (a pooled one when available — see + * ttAcquire()); the callback receives the instance's * [$this, 'traverseInternal'] array as its $traverse and Type::traverse() * receives [$this, 'mapInternal'] — the same PHP callables the twin hands * out, so a callback inspecting them sees no difference. @@ -83,6 +84,47 @@ class ActiveTraversalScope ActiveTraversalScope &operator=(const ActiveTraversalScope &) = delete; }; +/* Instances of finished traversals, handed to the next map() instead of a + * new one: an instance nothing outlived the traversal with (refcount 1 — + * the callables handed out were released) is reset to what the constructor + * leaves, so the next traversal cannot tell it from a fresh one; a + * self-analysis runs a million and a half traversals. */ +#define PT_TT_POOL_LIMIT 16 + +static zend_object *pt_tt_pool[PT_TT_POOL_LIMIT]; +static uint32_t pt_tt_pool_count = 0; + +/* an instance with $cb and $memo null; NULL = pending exception */ +static zend_object *ttAcquire() +{ + while (pt_tt_pool_count > 0) { + zend_object *object = pt_tt_pool[--pt_tt_pool_count]; + if (EXPECTED(object->ce == pt_ce_type_traverser)) return object; + OBJ_RELEASE(object); + } + zval object; + if (UNEXPECTED(object_init_ex(&object, pt_ce_type_traverser) != SUCCESS)) return NULL; + return Z_OBJ(object); +} + +/* releases the map()'s own reference — into the pool when it is the last */ +static void ttRelease(zend_object *object) +{ + if (GC_REFCOUNT(object) != 1 || pt_tt_pool_count >= PT_TT_POOL_LIMIT || object->properties != NULL || (GC_FLAGS(object) & IS_OBJ_WEAKLY_REFERENCED) != 0) { + OBJ_RELEASE(object); + return; + } + /* pooled before the old values go: a destructor they run may map() */ + zval cb, memo; + ZVAL_COPY_VALUE(&cb, OBJ_PROP_NUM(object, slots::cb)); + ZVAL_COPY_VALUE(&memo, OBJ_PROP_NUM(object, slots::memo)); + ZVAL_NULL(OBJ_PROP_NUM(object, slots::cb)); + ZVAL_NULL(OBJ_PROP_NUM(object, slots::memo)); + pt_tt_pool[pt_tt_pool_count++] = object; + zval_ptr_dtor(&cb); + zval_ptr_dtor(&memo); +} + namespace phpstanturbo { /* Mirrors PHPStan\Type\TypeTraverser. State lives in the PHP object's $cb. */ @@ -96,28 +138,36 @@ class TypeTraverser * UNDEF = pending exception */ static zv::Val map(zval *type, zval *cb) { - zval object; - if (UNEXPECTED(object_init_ex(&object, pt_ce_type_traverser) != SUCCESS)) return zv::Val(); - zv::Val holder = zv::Val::adopt(object); - TypeTraverser traverser(Z_OBJ(object)); + zend_object *object = ttAcquire(); + if (UNEXPECTED(object == NULL)) return zv::Val(); + TypeTraverser traverser(object); traverser.construct(cb); - ActiveTraversalScope active(Z_OBJ(object)); - return traverser.mapInternal(type); + zv::Val result; + { + ActiveTraversalScope active(object); + result = traverser.mapInternal(type); + } + ttRelease(object); + return result; } /* mapMemoized(): map() with `$self->memo = [];` */ static zv::Val mapMemoized(zval *type, zval *cb) { - zval object; - if (UNEXPECTED(object_init_ex(&object, pt_ce_type_traverser) != SUCCESS)) return zv::Val(); - zv::Val holder = zv::Val::adopt(object); - TypeTraverser traverser(Z_OBJ(object)); + zend_object *object = ttAcquire(); + if (UNEXPECTED(object == NULL)) return zv::Val(); + TypeTraverser traverser(object); traverser.construct(cb); - zval *memo = OBJ_PROP_NUM(Z_OBJ(object), slots::memo); + zval *memo = OBJ_PROP_NUM(object, slots::memo); zval_ptr_dtor(memo); ZVAL_EMPTY_ARRAY(memo); - ActiveTraversalScope active(Z_OBJ(object)); - return traverser.mapInternal(type); + zv::Val result; + { + ActiveTraversalScope active(object); + result = traverser.mapInternal(type); + } + ttRelease(object); + return result; } /* __construct(): the callback as given. A TypeTraverserCallable is kept @@ -237,6 +287,9 @@ void pt_type_traverser_rshutdown() ZVAL_UNDEF(&pt_tt_active[i].traverseCallable); } pt_tt_active_depth = 0; + while (pt_tt_pool_count > 0) { + OBJ_RELEASE(pt_tt_pool[--pt_tt_pool_count]); + } } bool pt_type_traverser_map(zval *out, zval *type, zval *cb) From 268bab2d463789d93615c3f0aadf7a706ace0f45 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 20 Oct 2026 15:51:58 +0200 Subject: [PATCH 06/13] Build StaticType's callbacks as native closures Each transformStaticType() created a holder object and a Closure over one of its methods (a copy of the function included). A native closure is one object carrying the body and the captured values. -0.26% instructions on the single-process benchmark. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01MMNnG2Zo7wgvSZCzjdk17X --- turbo-ext/src/StaticType.cpp | 197 ++++++++++++----------------------- 1 file changed, 64 insertions(+), 133 deletions(-) diff --git a/turbo-ext/src/StaticType.cpp b/turbo-ext/src/StaticType.cpp index dfad58674f2..541664d0555 100644 --- a/turbo-ext/src/StaticType.cpp +++ b/turbo-ext/src/StaticType.cpp @@ -24,15 +24,16 @@ * * The closures the twin creates — `fn (Type $type): Type => * $this->transformStaticType($type, $scope)` for the prototype - * reflections, the TypeTraverser::map() callback inside it, the - * RecursionGuard::run() thunk, and the TemplateTypeMap::map() callback of - * getStaticObjectType() — are Closures over the methods of the internal - * PHPStanTurbo\StaticTypeCallbacks holder, which keeps the captured values - * in its slots (an internal detail with no PHP twin, like the generalize() - * holder in TypeTraits.cpp). + * reflections, the TypeTraverser::map() callback inside it and the + * RecursionGuard::run() thunk — are native closures (Engine.h) over the + * captured values; the static TemplateTypeMap::map() callback of + * getStaticObjectType() is a Closure over the internal + * PHPStanTurbo\StaticTypeCallbacks holder's toArgument() (an internal + * detail with no PHP twin, like the generalize() holder in TypeTraits.cpp). */ #include "TypeTraits.h" +#include "Engine.h" #include "generated/StaticType.h" namespace slots = ptdecl::StaticType::slot; @@ -40,13 +41,15 @@ namespace sigs = ptdecl::StaticType::sig; zend_class_entry *pt_ce_static_type = nullptr; -/* the callback holder and its methods */ +/* the callback holder and its method */ static zend_class_entry *pt_ce_static_type_callbacks = nullptr; -static zend_function *pt_static_type_callbacks_transform = nullptr; -static zend_function *pt_static_type_callbacks_map = nullptr; -static zend_function *pt_static_type_callbacks_guard = nullptr; static zend_function *pt_static_type_callbacks_to_argument = nullptr; +/* the bodies of the native closures (after the class) */ +static void transformCallbackBody(zval *captures, uint32_t argc, zval *argv, zval *return_value); +static void mapCallbackBody(zval *captures, uint32_t argc, zval *argv, zval *return_value); +static void guardCallbackBody(zval *captures, uint32_t argc, zval *argv, zval *return_value); + /* the handlers a $this-call is checked against before the direct path */ static void ZEND_FASTCALL stGetStaticObjectType(INTERNAL_FUNCTION_PARAMETERS); static void ZEND_FASTCALL stGetClassReflection(INTERNAL_FUNCTION_PARAMETERS); @@ -384,7 +387,9 @@ class StaticType if (UNEXPECTED(classReflection.isUndef())) return zv::Val(); } /* fn (Type $type): Type => $this->transformStaticType($type, $scope) */ - zv::Val callback = callbackHolder(pt_static_type_callbacks_transform, self, scope, NULL, NULL); + zval selfZv; + ZVAL_OBJ(&selfZv, self); + zv::Val callback = pt_native_closure(&transformCallbackBody, &selfZv, scope); ZVAL_COPY_VALUE(&args[0], naked.raw()); ZVAL_COPY_VALUE(&args[1], classReflection.raw()); ZVAL_FALSE(&args[2]); @@ -448,7 +453,9 @@ class StaticType * UNDEF = pending exception */ zv::Val transformStaticType(zval *type, zval *scope) const { - zv::Val callback = callbackHolder(pt_static_type_callbacks_map, self, scope, NULL, NULL); + zval selfZv; + ZVAL_OBJ(&selfZv, self); + zv::Val callback = pt_native_closure(&mapCallbackBody, &selfZv, scope); return pt_type_traverser_map_of(type, callback.raw()); } @@ -507,7 +514,7 @@ class StaticType if (!isFinal || zv::Ref(mapped.raw()).instanceOf(pt_ce_this_type)) { /* RecursionGuard::run($type, static fn () => $traverse($type)) */ - zv::Val thunk = callbackHolder(pt_static_type_callbacks_guard, NULL, NULL, mapped.raw(), traverse); + zv::Val thunk = pt_native_closure(&guardCallbackBody, mapped.raw(), traverse); return pt_type_recursion_guard_run(mapped.raw(), thunk.raw()); } @@ -713,32 +720,6 @@ class StaticType return pt_type_call(self, PT_LC("getclassstringtype"), 0, NULL); } - /* a Closure over one of the holder's methods with the captured values - * in its slots (each borrowed, NULL for none) */ - static zv::Val callbackHolder(zend_function *fn, zend_object *staticType, zval *scope, zval *type, zval *traverse) - { - zval holder; - object_init_ex(&holder, pt_ce_static_type_callbacks); - zv::ObjRef holderRef(&holder); - if (staticType != NULL) { - zval staticTypeZv; - ZVAL_OBJ(&staticTypeZv, staticType); - holderRef.propAtWrite(slots::subtractedType, zv::Val::copyOf(zv::Ref(&staticTypeZv))); - } - if (scope != NULL) { - holderRef.propAtWrite(slots::staticObjectType, zv::Val::copyOf(zv::Ref(scope))); - } - if (type != NULL) { - holderRef.propAtWrite(slots::baseClass, zv::Val::copyOf(zv::Ref(type))); - } - if (traverse != NULL) { - holderRef.propAtWrite(slots::methodCache, zv::Val::copyOf(zv::Ref(traverse))); - } - zv::Val closure = pt_type_closure_over(fn, pt_ce_static_type_callbacks, Z_OBJ(holder)); - zval_ptr_dtor(&holder); /* the closure holds its own reference */ - return closure; - } - private: zend_object *self; @@ -760,6 +741,43 @@ class StaticType using phpstanturbo::StaticType; +/* `fn (Type $type): Type => $this->transformStaticType($type, $scope)`, + * capturing [$this, $scope] */ +static void transformCallbackBody(zval *captures, uint32_t argc, zval *argv, zval *return_value) +{ + if (UNEXPECTED(argc < 1 || Z_TYPE_P(zv::Ref(&argv[0]).deref().raw()) != IS_OBJECT)) { + zend_throw_error(NULL, "phpstan_turbo: StaticType callback called without a type"); + return; + } + zv::Val result = StaticType(Z_OBJ(captures[0])).transformStaticType(zv::Ref(&argv[0]).deref().raw(), &captures[1]); + if (UNEXPECTED(result.isUndef())) return; + *return_value = result.take(); +} + +/* the TypeTraverser::map() callback of transformStaticType(), capturing + * [$this, $scope] */ +static void mapCallbackBody(zval *captures, uint32_t argc, zval *argv, zval *return_value) +{ + if (UNEXPECTED(argc < 2 || Z_TYPE_P(zv::Ref(&argv[0]).deref().raw()) != IS_OBJECT)) { + zend_throw_error(NULL, "phpstan_turbo: StaticType callback called without a type and its traverse callable"); + return; + } + zv::Val result = StaticType(Z_OBJ(captures[0])).mapStaticType(zv::Ref(&argv[0]).deref().raw(), &captures[1], zv::Ref(&argv[1]).deref().raw()); + if (UNEXPECTED(result.isUndef())) return; + *return_value = result.take(); +} + +/* the RecursionGuard::run() thunk `static fn () => $traverse($type)`, + * capturing [$type, $traverse] */ +static void guardCallbackBody(zval *captures, uint32_t argc, zval *argv, zval *return_value) +{ + (void) argc; + (void) argv; + zv::Val result = pt_type_call_callable(&captures[1], 1, &captures[0]); + if (UNEXPECTED(result.isUndef())) return; + *return_value = result.take(); +} + bool pt_static_type_new(zval *out, zval *classReflection, zval *subtractedType) { return pt_val_into(StaticType::create(classReflection, subtractedType), out); @@ -786,59 +804,6 @@ zv::Val pt_static_type_this_class_name(zend_object *self) { return StaticType(se #define PT_THIS StaticType(Z_OBJ_P(ZEND_THIS)) -/* the holder's $this, an object of the holder class; NULL with an Error - * pending */ -[[nodiscard]] static zend_object *callbackHolderThis(zval *thisZv) -{ - if (UNEXPECTED(Z_TYPE_P(thisZv) != IS_OBJECT)) { - zend_throw_error(NULL, "phpstan_turbo: StaticType callback called without its holder"); - return NULL; - } - return Z_OBJ_P(thisZv); -} - -/* StaticTypeCallbacks::transform(Type $type): Type — the prototype - * reflections' `fn (Type $type): Type => $this->transformStaticType($type, $scope)` */ -static void ZEND_FASTCALL callbackTransform(INTERNAL_FUNCTION_PARAMETERS) -{ - zval *type; - if (!zp::parse(execute_data, type)) RETURN_THROWS(); - zend_object *holder = callbackHolderThis(ZEND_THIS); - if (UNEXPECTED(holder == NULL)) RETURN_THROWS(); - zval *staticType = OBJ_PROP_NUM(holder, slots::subtractedType); - if (UNEXPECTED(Z_TYPE_P(staticType) != IS_OBJECT)) { - zend_throw_error(NULL, "phpstan_turbo: StaticType callback holder without its type"); - RETURN_THROWS(); - } - PT_RETURN_VAL(StaticType(Z_OBJ_P(staticType)).transformStaticType(type, OBJ_PROP_NUM(holder, slots::staticObjectType))); -} - -/* StaticTypeCallbacks::map(Type $type, callable $traverse): Type — the - * TypeTraverser::map() callback of transformStaticType() */ -static void ZEND_FASTCALL callbackMap(INTERNAL_FUNCTION_PARAMETERS) -{ - zval *type, *traverse; - if (!zp::parse(execute_data, type, traverse)) RETURN_THROWS(); - zend_object *holder = callbackHolderThis(ZEND_THIS); - if (UNEXPECTED(holder == NULL)) RETURN_THROWS(); - zval *staticType = OBJ_PROP_NUM(holder, slots::subtractedType); - if (UNEXPECTED(Z_TYPE_P(staticType) != IS_OBJECT)) { - zend_throw_error(NULL, "phpstan_turbo: StaticType callback holder without its type"); - RETURN_THROWS(); - } - PT_RETURN_VAL(StaticType(Z_OBJ_P(staticType)).mapStaticType(type, OBJ_PROP_NUM(holder, slots::staticObjectType), traverse)); -} - -/* StaticTypeCallbacks::guard(): Type — the RecursionGuard::run() thunk - * `static fn () => $traverse($type)` */ -static void ZEND_FASTCALL callbackGuard(INTERNAL_FUNCTION_PARAMETERS) -{ - ZEND_PARSE_PARAMETERS_NONE(); - zend_object *holder = callbackHolderThis(ZEND_THIS); - if (UNEXPECTED(holder == NULL)) RETURN_THROWS(); - PT_RETURN_VAL(pt_type_call_callable(OBJ_PROP_NUM(holder, slots::methodCache), 1, OBJ_PROP_NUM(holder, slots::baseClass))); -} - /* StaticTypeCallbacks::toArgument(string $name, Type $type): Type — the * TemplateTypeMap::map() callback of getStaticObjectType() */ static void ZEND_FASTCALL callbackToArgument(INTERNAL_FUNCTION_PARAMETERS) @@ -848,11 +813,11 @@ static void ZEND_FASTCALL callbackToArgument(INTERNAL_FUNCTION_PARAMETERS) PT_RETURN_VAL(pt_type_template_type_helper_to_argument(type)); } -/* the holder's methods entered without a frame (TypeOps.h, pt_direct_invoke): - * the callable is recognised by its handler (a plain callable) or by the - * scope and name of the Closure's function copy; the arguments must be - * what the handler's zpp would accept — anything else, or a holder without - * its type, is left to the engine path */ +/* the holder's toArgument() entered without a frame (TypeOps.h, + * pt_direct_invoke): the callable is recognised by its handler (a plain + * callable) or by the scope and name of the Closure's function copy; the + * arguments must be what the handler's zpp would accept — anything else is + * left to the engine path */ bool pt_static_type_callbacks_direct_invoke(const zend_function *fn, zend_object *object, uint32_t argc, zval *argv, zval *retval, bool &handled) { zif_handler handler = PT_INTERNAL_HANDLER(fn); @@ -870,31 +835,7 @@ bool pt_static_type_callbacks_direct_invoke(const zend_function *fn, zend_object *retval = result.take(); return true; } - if (object == NULL || object->ce != pt_ce_static_type_callbacks) return false; - zv::Val result; - if (handler == callbackTransform || (inHolder && zend_string_equals_literal(name, "transform"))) { - zval *staticType = OBJ_PROP_NUM(object, slots::subtractedType); - if (argc != 1 || Z_TYPE_P(argv) != IS_OBJECT || Z_TYPE_P(staticType) != IS_OBJECT) return false; - handled = true; - result = StaticType(Z_OBJ_P(staticType)).transformStaticType(argv, OBJ_PROP_NUM(object, slots::staticObjectType)); - } else if (handler == callbackMap || (inHolder && zend_string_equals_literal(name, "map"))) { - zval *staticType = OBJ_PROP_NUM(object, slots::subtractedType); - if (argc != 2 || Z_TYPE_P(argv) != IS_OBJECT || Z_TYPE_P(staticType) != IS_OBJECT) return false; - handled = true; - result = StaticType(Z_OBJ_P(staticType)).mapStaticType(argv, OBJ_PROP_NUM(object, slots::staticObjectType), &argv[1]); - } else if (handler == callbackGuard || (inHolder && zend_string_equals_literal(name, "guard"))) { - if (argc != 0) return false; - handled = true; - result = pt_type_call_callable(OBJ_PROP_NUM(object, slots::methodCache), 1, OBJ_PROP_NUM(object, slots::baseClass)); - } else { - return false; - } - if (UNEXPECTED(result.isUndef())) { - ZVAL_UNDEF(retval); - return false; - } - *retval = result.take(); - return true; + return false; } /* the delegating bodies: $this->getStaticObjectType()->method(...$args) @@ -1025,21 +966,11 @@ PT_MINIT_REGISTRATION(pt_register_static_type) * `cls.method(...)` lines with the twin's methods, and the holder's * have none */ reg::Class holder("PHPStanTurbo\\StaticTypeCallbacks"); - holder.privateNullProperty("staticType"); - holder.privateNullProperty("scope"); - holder.privateNullProperty("type"); - holder.privateNullProperty("traverse"); - holder.method("transform", reg::Public, 1, { reg::obj("type", ptcls::type) }, callbackTransform, &ptret::type); - holder.method("map", reg::Public, 2, { reg::obj("type", ptcls::type), reg::callableArg("traverse") }, callbackMap, &ptret::type); - holder.method("guard", reg::Public, 0, {}, callbackGuard, &ptret::type); holder.method("toArgument", reg::PublicStatic, 2, { reg::stringArg("name"), reg::obj("type", ptcls::type) }, callbackToArgument, &ptret::type); pt_ce_static_type_callbacks = holder.register_(); pt_ce_static_type_callbacks->ce_flags |= ZEND_ACC_FINAL; - pt_static_type_callbacks_transform = (zend_function *) zend_hash_str_find_ptr(&PT_CE(pt_ce_static_type_callbacks, function_table), PT_LC("transform")); - pt_static_type_callbacks_map = (zend_function *) zend_hash_str_find_ptr(&PT_CE(pt_ce_static_type_callbacks, function_table), PT_LC("map")); - pt_static_type_callbacks_guard = (zend_function *) zend_hash_str_find_ptr(&PT_CE(pt_ce_static_type_callbacks, function_table), PT_LC("guard")); pt_static_type_callbacks_to_argument = (zend_function *) zend_hash_str_find_ptr(&PT_CE(pt_ce_static_type_callbacks, function_table), PT_LC("toargument")); - ZEND_ASSERT(pt_static_type_callbacks_transform != NULL && pt_static_type_callbacks_map != NULL && pt_static_type_callbacks_guard != NULL && pt_static_type_callbacks_to_argument != NULL); + ZEND_ASSERT(pt_static_type_callbacks_to_argument != NULL); reg::Class cls("PHPStan\\Type\\StaticType"); ptdecl::StaticType::declareClass(cls); From b1999445dd7e9cd265bfda5530fa2de82b29abc3 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 20 Oct 2026 15:51:58 +0200 Subject: [PATCH 07/13] Build ObjectType's guarded callbacks as native closures The RecursionGuard and TemplateTypeMap::map() callbacks were a holder object plus a Closure over its __invoke(); a native closure replaces both, and the by-reference capture carries the offsetSet() value type back. -0.13% instructions on the single-process benchmark (within noise; it removes the holder's invocation path). Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01MMNnG2Zo7wgvSZCzjdk17X --- turbo-ext/src/ObjectType.cpp | 124 +++++++++++++++-------------------- turbo-ext/src/TypeTraits.cpp | 10 --- turbo-ext/src/TypeTraits.h | 7 +- 3 files changed, 56 insertions(+), 85 deletions(-) diff --git a/turbo-ext/src/ObjectType.cpp b/turbo-ext/src/ObjectType.cpp index b1d908490df..37587a5e1d9 100644 --- a/turbo-ext/src/ObjectType.cpp +++ b/turbo-ext/src/ObjectType.cpp @@ -24,15 +24,15 @@ * ObjectType (`$type->className`, `$type->subtractedType`) are read * directly, as the twin does from inside the class. * - * The closures the twin hands to RecursionGuard::run() and the - * `static fn (Type $type): Type => $type` the prototype reflections take - * are Closures over the internal PHPStanTurbo\ObjectTypeCallback holder - * (an internal detail with no PHP twin, like the generalize() holder in - * TypeTraits.cpp): __invoke() replays the captured call, identity() - * returns its argument. + * The closures the twin hands to RecursionGuard::run() are native closures + * (Engine.h) replaying the captured call; the `static fn (Type $type): Type + * => $type` the prototype reflections take is a Closure over identity() of + * the internal PHPStanTurbo\ObjectTypeCallback holder (an internal detail + * with no PHP twin, like the generalize() holder in TypeTraits.cpp). */ #include "TypeTraits.h" +#include "Engine.h" #include "generated/ObjectType.h" #include "AcceptorValues.h" @@ -258,13 +258,12 @@ static void pt_ot_cache_unset(zval *cache, zend_string *key) /* }}} */ -/* {{{ the callback holder: PHPStanTurbo\ObjectTypeCallback — the closures - * RecursionGuard::run() / runOnObjectIdentity() / TemplateTypeMap::map() - * receive, replaying the captured call from __invoke(); identity() is the - * `static fn (Type $type): Type => $type` of the prototype reflections */ +/* {{{ the callbacks: the native closures RecursionGuard::run() / + * runOnObjectIdentity() / TemplateTypeMap::map() receive, replaying the + * captured call; the PHPStanTurbo\ObjectTypeCallback holder's identity() is + * the `static fn (Type $type): Type => $type` of the prototype reflections */ static zend_class_entry *pt_ce_object_type_callback = nullptr; -static zend_function *pt_object_type_callback_invoke_fn = nullptr; static zend_function *pt_object_type_callback_identity = nullptr; enum pt_ot_callback_kind @@ -294,29 +293,30 @@ enum pt_ot_callback_kind PT_OTC_ERROR_TYPE, }; -static void ZEND_FASTCALL objectTypeCallbackInvoke(INTERNAL_FUNCTION_PARAMETERS); static void ZEND_FASTCALL objectTypeCallbackIdentity(INTERNAL_FUNCTION_PARAMETERS); +static void otCallbackBody(zval *captures, uint32_t argc, zval *argv, zval *return_value); -/* the Closure over __invoke() of a holder capturing the call; *holder - * receives the holder object (owned) when the caller reads ->out back; - * UNDEF = pending exception */ -static zv::Val pt_ot_callback(pt_ot_callback_kind kind, zval *object, zval *arg, zval *scope, zval *holderOut = NULL) +/* the native closure replaying a call: captures [kind, object, arg, scope] + * (each borrowed, NULL for none) and, with outRef (an IS_REFERENCE), the + * reference the OFFSET_SET_PARAMETER_TYPES call writes its second type to */ +static zv::Val pt_ot_callback(pt_ot_callback_kind kind, zval *object, zval *arg, zval *scope, zval *outRef = NULL) { - zval holder; - object_init_ex(&holder, pt_ce_object_type_callback); - zv::ObjRef ref(&holder); - ref.propAtWrite(slots::subtractedType, zv::Val::integer(kind)); - ref.propAtWrite(slots::cachedParent, object != NULL ? zv::Val::copyOf(zv::Ref(object)) : zv::Val::null()); - ref.propAtWrite(slots::cachedInterfaces, arg != NULL ? zv::Val::copyOf(zv::Ref(arg)) : zv::Val::null()); - ref.propAtWrite(slots::currentAncestors, scope != NULL ? zv::Val::copyOf(zv::Ref(scope)) : zv::Val::null()); - zval closure; - pt_abi_create_closure(&closure, pt_object_type_callback_invoke_fn, pt_ce_object_type_callback, pt_ce_object_type_callback, Z_OBJ(holder)); - if (holderOut != NULL) { - ZVAL_COPY_VALUE(holderOut, &holder); /* the closure holds its own reference */ - } else { - zval_ptr_dtor(&holder); + zval captures[5]; + ZVAL_LONG(&captures[0], kind); + zval *given[3] = {object, arg, scope}; + for (uint32_t i = 0; i < 3; i++) { + if (given[i] != NULL) { + ZVAL_COPY_VALUE(&captures[i + 1], given[i]); + } else { + ZVAL_NULL(&captures[i + 1]); + } } - return zv::Val::adopt(closure); + uint32_t count = 4; + if (outRef != NULL) { + ZVAL_COPY_VALUE(&captures[4], outRef); + count = 5; + } + return pt_native_closure_new(&otCallbackBody, count, captures, 1u << 4); } /* static fn (Type $type): Type => $type */ @@ -1983,11 +1983,13 @@ class ObjectType /* $acceptedValueType = new NeverType(), overwritten by the closure */ zv::Val acceptedValueType = pt_type_new_never_type(); if (UNEXPECTED(acceptedValueType.isUndef())) return zv::Val(); - zval holder; - zv::Val acceptedOffsetType = guarded(PT_OTC_OFFSET_SET_PARAMETER_TYPES, NULL, NULL, NULL, &holder); - zv::Val holderVal = zv::Val::adopt(holder); + zval outRef, none; + ZVAL_NULL(&none); + ZVAL_NEW_REF(&outRef, &none); + zv::Val outRefVal = zv::Val::adopt(outRef); + zv::Val acceptedOffsetType = guarded(PT_OTC_OFFSET_SET_PARAMETER_TYPES, NULL, NULL, NULL, outRefVal.raw()); if (UNEXPECTED(acceptedOffsetType.isUndef())) return zv::Val(); - zval *out = OBJ_PROP_NUM(Z_OBJ(holder), slots::cachedDescription); + zval *out = Z_REFVAL_P(outRefVal.raw()); if (Z_TYPE_P(out) == IS_OBJECT) { acceptedValueType = zv::Val::copyOf(zv::Ref(out)); } @@ -3004,11 +3006,11 @@ class ObjectType } /* RecursionGuard::run($this, ); UNDEF = pending exception */ - zv::Val guarded(pt_ot_callback_kind kind, zval *object, zval *arg, zval *scope, zval *holderOut = NULL) const + zv::Val guarded(pt_ot_callback_kind kind, zval *object, zval *arg, zval *scope, zval *outRef = NULL) const { zval selfZv; ZVAL_OBJ(&selfZv, self); - zv::Val callback = pt_ot_callback(kind, object != NULL ? object : &selfZv, arg, scope, holderOut); + zv::Val callback = pt_ot_callback(kind, object != NULL ? object : &selfZv, arg, scope, outRef); if (UNEXPECTED(callback.isUndef())) return zv::Val(); return pt_type_recursion_guard_run(&selfZv, callback.raw()); } @@ -3330,15 +3332,15 @@ zv::Val pt_object_type_referenced_classes_callback(zval *type) #define PT_THIS ObjectType(Z_OBJ_P(ZEND_THIS)) -/* the body of ObjectTypeCallback::__invoke(...$args): replays the captured - * call (the arguments are ignored, as the twins' closures ignore them); - * UNDEF = pending exception */ -zv::Val pt_object_type_callback_invoke(zend_object *holder) +/* the replay of a pt_ot_callback() closure's captured call (the arguments + * are ignored, as the twins' closures ignore them); UNDEF = pending + * exception */ +static zv::Val otCallbackRun(zval *captures) { - zend_long kind = Z_LVAL_P(OBJ_PROP_NUM(holder, slots::subtractedType)); - zval *object = OBJ_PROP_NUM(holder, slots::cachedParent); - zval *arg = OBJ_PROP_NUM(holder, slots::cachedInterfaces); - zval *scope = OBJ_PROP_NUM(holder, slots::currentAncestors); + zend_long kind = Z_LVAL(captures[0]); + zval *object = &captures[1]; + zval *arg = &captures[2]; + zval *scope = &captures[3]; zv::Args args{arg, scope}; switch (kind) { case PT_OTC_HAS_PROPERTY: @@ -3414,7 +3416,7 @@ zv::Val pt_object_type_callback_invoke(zend_object *holder) if (kind == PT_OTC_OFFSET_SET_PARAMETER_TYPES) { zv::Val acceptedValueType = pt_type_call(Z_OBJ_P(valueParameter), PT_LC("gettype"), 0, NULL); if (UNEXPECTED(acceptedValueType.isUndef())) return zv::Val(); - zv::ObjRef(holder).propAtWrite(slots::cachedDescription, std::move(acceptedValueType)); + zv::Ref(&captures[4]).deref().assign(std::move(acceptedValueType)); } return pt_type_call(Z_OBJ_P(offsetParameter), PT_LC("gettype"), 0, NULL); } @@ -3430,24 +3432,13 @@ zv::Val pt_object_type_callback_invoke(zend_object *holder) } } -/* ObjectTypeCallback::__invoke(...$args) */ -static void ZEND_FASTCALL objectTypeCallbackInvoke(INTERNAL_FUNCTION_PARAMETERS) -{ - if (UNEXPECTED(Z_TYPE_P(ZEND_THIS) != IS_OBJECT)) { - zend_throw_error(NULL, "phpstan_turbo: ObjectTypeCallback called without its holder"); - RETURN_THROWS(); - } - PT_RETURN_VAL(pt_object_type_callback_invoke(Z_OBJ_P(ZEND_THIS))); -} - -zif_handler pt_object_type_callback_invoke_handler() -{ - return objectTypeCallbackInvoke; -} - -zend_class_entry *pt_object_type_callback_ce() +static void otCallbackBody(zval *captures, uint32_t argc, zval *argv, zval *return_value) { - return pt_ce_object_type_callback; + (void) argc; + (void) argv; + zv::Val result = otCallbackRun(captures); + if (UNEXPECTED(result.isUndef())) return; + *return_value = result.take(); } /* ObjectTypeCallback::identity(Type $type): Type */ @@ -3622,18 +3613,11 @@ PT_MINIT_REGISTRATION(pt_register_object_type) * `cls.method(...)` lines with the twin's methods, and the holder's * methods have none */ reg::Class holder("PHPStanTurbo\\ObjectTypeCallback"); - holder.privateLongProperty("kind", 0); - holder.privateNullProperty("object"); - holder.privateNullProperty("arg"); - holder.privateNullProperty("scope"); - holder.privateNullProperty("out"); - holder.method("__invoke", reg::Public, 0, { reg::variadicObj("args", "mixed") }, objectTypeCallbackInvoke); holder.method("identity", reg::PublicStatic, 1, { reg::obj("type", ptcls::type) }, objectTypeCallbackIdentity, &ptret::type); pt_ce_object_type_callback = holder.register_(); pt_ce_object_type_callback->ce_flags |= ZEND_ACC_FINAL; - pt_object_type_callback_invoke_fn = (zend_function *) zend_hash_str_find_ptr(&PT_CE(pt_ce_object_type_callback, function_table), PT_LC("__invoke")); pt_object_type_callback_identity = (zend_function *) zend_hash_str_find_ptr(&PT_CE(pt_ce_object_type_callback, function_table), PT_LC("identity")); - ZEND_ASSERT(pt_object_type_callback_invoke_fn != NULL && pt_object_type_callback_identity != NULL); + ZEND_ASSERT(pt_object_type_callback_identity != NULL); reg::Class cls("PHPStan\\Type\\ObjectType"); ptdecl::ObjectType::declareClass(cls); diff --git a/turbo-ext/src/TypeTraits.cpp b/turbo-ext/src/TypeTraits.cpp index 35b6db5ab3a..c5f9ddd13b5 100644 --- a/turbo-ext/src/TypeTraits.cpp +++ b/turbo-ext/src/TypeTraits.cpp @@ -2082,16 +2082,6 @@ bool pt_direct_invoke(const zend_function *fn, zend_object *object, uint32_t arg if (EXPECTED(object != NULL && object->ce == pt_ce_native_closure)) return pt_native_closure_invoke(object, argc, argv, retval); } else if (handler == invokeNativeCallback || (scope == pt_ce_native_callback && zend_string_equals_literal(fn->common.function_name, "__invoke"))) { if (EXPECTED(object != NULL && object->ce == pt_ce_native_callback)) return pt_native_callback_invoke(object, argc, argv, retval); - } else if (handler == pt_object_type_callback_invoke_handler() || (scope == pt_object_type_callback_ce() && zend_string_equals_literal(fn->common.function_name, "__invoke"))) { - if (EXPECTED(object != NULL && object->ce == pt_object_type_callback_ce())) { - zv::Val result = pt_object_type_callback_invoke(object); - if (UNEXPECTED(result.isUndef())) { - ZVAL_UNDEF(retval); - return false; - } - *retval = result.take(); - return true; - } } else if (handler == pt_type_traverser_map_internal_handler() || handler == pt_type_traverser_traverse_internal_handler()) { /* the twins' (Type $type) parameter: one object, as Z_PARAM_OBJECT * delivers it */ diff --git a/turbo-ext/src/TypeTraits.h b/turbo-ext/src/TypeTraits.h index 77c45c5e953..710bffca6d3 100644 --- a/turbo-ext/src/TypeTraits.h +++ b/turbo-ext/src/TypeTraits.h @@ -1366,7 +1366,7 @@ zv::Val pt_type_utils_get_integer_ranges(zval *type); /* merged from the parallel port branch */ /* {{{ direct dispatch (TypeOps.h): the callables native code hands around - * — the PHPStanTurbo\NativeCallback and PHPStanTurbo\ObjectTypeCallback + * — the PHPStanTurbo\NativeClosure and PHPStanTurbo\NativeCallback * holders' __invoke() and TypeTraverser::mapInternal() / * traverseInternal() — entered without a frame by pt_call_fci() and * pt_type_call_callable() when a resolved callable is one of them */ @@ -1374,7 +1374,6 @@ zv::Val pt_type_utils_get_integer_ranges(zval *type); /* the handlers, for identifying a resolved callable (a Closure over one * carries the same handler in its function copy) */ zif_handler pt_native_callback_invoke_handler(); -zif_handler pt_object_type_callback_invoke_handler(); /* ObjectType.cpp */ zif_handler pt_type_traverser_map_internal_handler(); /* TypeTraverser.cpp */ zif_handler pt_type_traverser_traverse_internal_handler(); @@ -1383,7 +1382,6 @@ zif_handler pt_type_traverser_traverse_internal_handler(); * *retval released), and mapInternal($type) / traverseInternal($type) of * a TypeTraverser instance (UNDEF = pending exception) */ [[nodiscard]] bool pt_native_callback_invoke(zend_object *holder, uint32_t argc, zval *argv, zval *retval); -zv::Val pt_object_type_callback_invoke(zend_object *holder); zv::Val pt_type_traverser_map_internal(zend_object *traverser, zval *type); zv::Val pt_type_traverser_traverse_internal(zend_object *traverser, zval *type); @@ -1392,10 +1390,9 @@ zv::Val pt_type_traverser_traverse_internal(zend_object *traverser, zval *type); * function's copy by its own trampoline, so a closure is recognised by the * copy's scope and name, a plain callable by its handler */ zend_class_entry *pt_native_callback_ce(); -zend_class_entry *pt_object_type_callback_ce(); /* ObjectType.cpp */ /* the direct call of a resolved internal callable (its function and bound - * object) when it is one of the four; handled = false when it is not + * object) when it is one of them; handled = false when it is not * (nothing was called); false with handled = true when the call threw * (*retval released) */ bool pt_direct_invoke(const zend_function *fn, zend_object *object, uint32_t argc, zval *argv, zval *retval, bool &handled); From 08815ee309513b113effd08ebca390039d567ce0 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 20 Oct 2026 16:04:29 +0200 Subject: [PATCH 08/13] Share the reasonless IsSuperTypeOfResult instances A self-analysis created 1.4M results, nearly all without reasons, and and()/or()/extremeIdentity()/maxMin() merged three empty arrays per call into yet another one. createFromTrinaryLogic() returns the createYes() / createNo() / createMaybe() instance for a result, the call sites that spelled new IsSuperTypeOfResult($result, []) use it, and the combinators skip the merging when no operand has reasons and return a shared instance. -0.48% instructions, -0.60% cycles on the single-process benchmark. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01MMNnG2Zo7wgvSZCzjdk17X --- src/Type/Accessory/AccessoryArrayListType.php | 8 +- .../AccessoryDecimalIntegerStringType.php | 5 +- .../Accessory/AccessoryLiteralStringType.php | 5 +- .../AccessoryLowercaseStringType.php | 5 +- .../Accessory/AccessoryNonEmptyStringType.php | 5 +- .../Accessory/AccessoryNonFalsyStringType.php | 5 +- .../Accessory/AccessoryNumericStringType.php | 5 +- .../AccessoryUppercaseStringType.php | 5 +- src/Type/Accessory/HasMethodType.php | 4 +- src/Type/Accessory/HasOffsetType.php | 5 +- src/Type/Accessory/HasOffsetValueType.php | 5 +- src/Type/Accessory/HasPropertyType.php | 6 +- src/Type/Accessory/NonEmptyArrayType.php | 5 +- src/Type/Accessory/OversizedArrayType.php | 5 +- src/Type/CallableType.php | 7 +- src/Type/CallableTypeHelper.php | 8 +- src/Type/ClassStringType.php | 2 +- src/Type/Constant/ConstantArrayType.php | 4 +- src/Type/IsSuperTypeOfResult.php | 66 ++++++++++++++--- src/Type/IterableType.php | 6 +- src/Type/ObjectShapeType.php | 2 +- src/Type/ObjectType.php | 2 +- turbo-ext/src/AccessoryArrayListType.cpp | 6 +- .../src/AccessoryDecimalIntegerStringType.cpp | 4 +- turbo-ext/src/AccessoryLiteralStringType.cpp | 4 +- .../src/AccessoryLowercaseStringType.cpp | 4 +- turbo-ext/src/AccessoryNonEmptyStringType.cpp | 4 +- turbo-ext/src/AccessoryNonFalsyStringType.cpp | 4 +- turbo-ext/src/AccessoryNumericStringType.cpp | 4 +- .../src/AccessoryUppercaseStringType.cpp | 4 +- turbo-ext/src/CallableType.cpp | 4 +- turbo-ext/src/CallableTypeHelper.cpp | 2 +- turbo-ext/src/ClassStringType.cpp | 2 +- turbo-ext/src/ConstantArrayType.cpp | 2 +- turbo-ext/src/HasMethodType.cpp | 4 +- turbo-ext/src/HasOffsetType.cpp | 4 +- turbo-ext/src/HasOffsetValueType.cpp | 4 +- turbo-ext/src/HasPropertyType.cpp | 4 +- turbo-ext/src/IsSuperTypeOfResult.cpp | 59 +++++++++++++-- turbo-ext/src/IterableType.cpp | 2 +- turbo-ext/src/NonEmptyArrayType.cpp | 4 +- turbo-ext/src/ObjectShapeType.cpp | 7 +- turbo-ext/src/ObjectType.cpp | 11 +-- turbo-ext/src/OversizedArrayType.cpp | 4 +- turbo-ext/src/TypeTraits.cpp | 19 +---- turbo-ext/src/TypeTraits.h | 11 ++- turbo-ext/src/generated/IsSuperTypeOfResult.h | 74 +++++++++++-------- 47 files changed, 242 insertions(+), 179 deletions(-) diff --git a/src/Type/Accessory/AccessoryArrayListType.php b/src/Type/Accessory/AccessoryArrayListType.php index 0b08101eb95..026784c7ace 100644 --- a/src/Type/Accessory/AccessoryArrayListType.php +++ b/src/Type/Accessory/AccessoryArrayListType.php @@ -104,7 +104,7 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult return $type->isSubTypeOf($this); } - return new IsSuperTypeOfResult($type->isList(), []); + return IsSuperTypeOfResult::createFromTrinaryLogic($type->isList()); } public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult @@ -114,15 +114,13 @@ public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult } if ($otherType instanceof self) { - return new IsSuperTypeOfResult( + return IsSuperTypeOfResult::createFromTrinaryLogic( TrinaryLogic::createYes(), - [], ); } - return new IsSuperTypeOfResult( + return IsSuperTypeOfResult::createFromTrinaryLogic( $otherType->isList()->and(TrinaryLogic::createMaybe()), - [], ); } diff --git a/src/Type/Accessory/AccessoryDecimalIntegerStringType.php b/src/Type/Accessory/AccessoryDecimalIntegerStringType.php index 90c671fda34..23a6e68819d 100644 --- a/src/Type/Accessory/AccessoryDecimalIntegerStringType.php +++ b/src/Type/Accessory/AccessoryDecimalIntegerStringType.php @@ -116,7 +116,7 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult $isDecimalIntegerString = $type->isDecimalIntegerString(); $result = $type->isString()->and($this->inverse ? $isDecimalIntegerString->negate() : $isDecimalIntegerString); - return new IsSuperTypeOfResult($result, []); + return IsSuperTypeOfResult::createFromTrinaryLogic($result); } public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult @@ -138,9 +138,8 @@ public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult $otherTypeResult = $otherType->isString()->and($this->inverse ? $otherType->isDecimalIntegerString()->negate() : $otherType->isDecimalIntegerString()); - return new IsSuperTypeOfResult( + return IsSuperTypeOfResult::createFromTrinaryLogic( $otherTypeResult->and($otherType->equals($this) ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()), - [], ); } diff --git a/src/Type/Accessory/AccessoryLiteralStringType.php b/src/Type/Accessory/AccessoryLiteralStringType.php index 80b6c0050b1..38a7cb318de 100644 --- a/src/Type/Accessory/AccessoryLiteralStringType.php +++ b/src/Type/Accessory/AccessoryLiteralStringType.php @@ -101,7 +101,7 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult return IsSuperTypeOfResult::createYes(); } - return new IsSuperTypeOfResult($type->isLiteralString(), []); + return IsSuperTypeOfResult::createFromTrinaryLogic($type->isLiteralString()); } public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult @@ -110,9 +110,8 @@ public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult return $otherType->isSuperTypeOf($this); } - return new IsSuperTypeOfResult( + return IsSuperTypeOfResult::createFromTrinaryLogic( $otherType->isLiteralString()->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()), - [], ); } diff --git a/src/Type/Accessory/AccessoryLowercaseStringType.php b/src/Type/Accessory/AccessoryLowercaseStringType.php index 4ef12bc70c1..984c7a6d200 100644 --- a/src/Type/Accessory/AccessoryLowercaseStringType.php +++ b/src/Type/Accessory/AccessoryLowercaseStringType.php @@ -98,7 +98,7 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult return IsSuperTypeOfResult::createYes(); } - return new IsSuperTypeOfResult($type->isLowercaseString(), []); + return IsSuperTypeOfResult::createFromTrinaryLogic($type->isLowercaseString()); } public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult @@ -107,9 +107,8 @@ public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult return $otherType->isSuperTypeOf($this); } - return new IsSuperTypeOfResult( + return IsSuperTypeOfResult::createFromTrinaryLogic( $otherType->isLowercaseString()->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()), - [], ); } diff --git a/src/Type/Accessory/AccessoryNonEmptyStringType.php b/src/Type/Accessory/AccessoryNonEmptyStringType.php index df3c2cd9854..a1761329aac 100644 --- a/src/Type/Accessory/AccessoryNonEmptyStringType.php +++ b/src/Type/Accessory/AccessoryNonEmptyStringType.php @@ -103,7 +103,7 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult return IsSuperTypeOfResult::createYes(); } - return new IsSuperTypeOfResult($type->isNonEmptyString(), []); + return IsSuperTypeOfResult::createFromTrinaryLogic($type->isNonEmptyString()); } public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult @@ -112,9 +112,8 @@ public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult return $otherType->isSuperTypeOf($this); } - return new IsSuperTypeOfResult( + return IsSuperTypeOfResult::createFromTrinaryLogic( $otherType->isNonEmptyString()->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()), - [], ); } diff --git a/src/Type/Accessory/AccessoryNonFalsyStringType.php b/src/Type/Accessory/AccessoryNonFalsyStringType.php index d441f4ef4f8..f95b1177a6f 100644 --- a/src/Type/Accessory/AccessoryNonFalsyStringType.php +++ b/src/Type/Accessory/AccessoryNonFalsyStringType.php @@ -102,7 +102,7 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult return IsSuperTypeOfResult::createYes(); } - return new IsSuperTypeOfResult($type->isNonFalsyString(), []); + return IsSuperTypeOfResult::createFromTrinaryLogic($type->isNonFalsyString()); } public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult @@ -115,9 +115,8 @@ public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult return IsSuperTypeOfResult::createYes(); } - return new IsSuperTypeOfResult( + return IsSuperTypeOfResult::createFromTrinaryLogic( $otherType->isNonFalsyString()->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()), - [], ); } diff --git a/src/Type/Accessory/AccessoryNumericStringType.php b/src/Type/Accessory/AccessoryNumericStringType.php index 8bffd940069..6cf9995168e 100644 --- a/src/Type/Accessory/AccessoryNumericStringType.php +++ b/src/Type/Accessory/AccessoryNumericStringType.php @@ -99,7 +99,7 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult return IsSuperTypeOfResult::createYes(); } - return new IsSuperTypeOfResult($type->isNumericString(), []); + return IsSuperTypeOfResult::createFromTrinaryLogic($type->isNumericString()); } public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult @@ -108,9 +108,8 @@ public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult return $otherType->isSuperTypeOf($this); } - return new IsSuperTypeOfResult( + return IsSuperTypeOfResult::createFromTrinaryLogic( $otherType->isNumericString()->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()), - [], ); } diff --git a/src/Type/Accessory/AccessoryUppercaseStringType.php b/src/Type/Accessory/AccessoryUppercaseStringType.php index 098656190df..ec915f2ac11 100644 --- a/src/Type/Accessory/AccessoryUppercaseStringType.php +++ b/src/Type/Accessory/AccessoryUppercaseStringType.php @@ -98,7 +98,7 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult return IsSuperTypeOfResult::createYes(); } - return new IsSuperTypeOfResult($type->isUppercaseString(), []); + return IsSuperTypeOfResult::createFromTrinaryLogic($type->isUppercaseString()); } public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult @@ -107,9 +107,8 @@ public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult return $otherType->isSuperTypeOf($this); } - return new IsSuperTypeOfResult( + return IsSuperTypeOfResult::createFromTrinaryLogic( $otherType->isUppercaseString()->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()), - [], ); } diff --git a/src/Type/Accessory/HasMethodType.php b/src/Type/Accessory/HasMethodType.php index 90f2ace74cc..889c523622a 100644 --- a/src/Type/Accessory/HasMethodType.php +++ b/src/Type/Accessory/HasMethodType.php @@ -106,7 +106,7 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult return $type->isSubTypeOf($this); } - return new IsSuperTypeOfResult($type->hasMethod($this->methodName), []); + return IsSuperTypeOfResult::createFromTrinaryLogic($type->hasMethod($this->methodName)); } public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult @@ -129,7 +129,7 @@ public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult $limit = TrinaryLogic::createMaybe(); } - return new IsSuperTypeOfResult($limit->and($otherType->hasMethod($this->methodName)), []); + return IsSuperTypeOfResult::createFromTrinaryLogic($limit->and($otherType->hasMethod($this->methodName))); } public function isAcceptedBy(Type $acceptingType, bool $strictTypes): AcceptsResult diff --git a/src/Type/Accessory/HasOffsetType.php b/src/Type/Accessory/HasOffsetType.php index 9666433b16c..0d300a83d20 100644 --- a/src/Type/Accessory/HasOffsetType.php +++ b/src/Type/Accessory/HasOffsetType.php @@ -100,7 +100,7 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult if ($this->equals($type)) { return IsSuperTypeOfResult::createYes(); } - return new IsSuperTypeOfResult($type->isOffsetAccessible()->and($type->hasOffsetValueType($this->offsetType)), []); + return IsSuperTypeOfResult::createFromTrinaryLogic($type->isOffsetAccessible()->and($type->hasOffsetValueType($this->offsetType))); } public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult @@ -109,9 +109,8 @@ public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult return $otherType->isSuperTypeOf($this); } - return new IsSuperTypeOfResult( + return IsSuperTypeOfResult::createFromTrinaryLogic( $otherType->isOffsetAccessible()->and($otherType->hasOffsetValueType($this->offsetType))->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()), - [], ); } diff --git a/src/Type/Accessory/HasOffsetValueType.php b/src/Type/Accessory/HasOffsetValueType.php index 135322a0d0f..3581f8f95af 100644 --- a/src/Type/Accessory/HasOffsetValueType.php +++ b/src/Type/Accessory/HasOffsetValueType.php @@ -109,7 +109,7 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult return IsSuperTypeOfResult::createYes(); } - $result = new IsSuperTypeOfResult($type->isOffsetAccessible()->and($type->hasOffsetValueType($this->offsetType)), []); + $result = IsSuperTypeOfResult::createFromTrinaryLogic($type->isOffsetAccessible()->and($type->hasOffsetValueType($this->offsetType))); return $result ->and($this->valueType->isSuperTypeOf($type->getOffsetValueType($this->offsetType))); @@ -121,11 +121,10 @@ public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult return $otherType->isSuperTypeOf($this); } - $result = new IsSuperTypeOfResult( + $result = IsSuperTypeOfResult::createFromTrinaryLogic( $otherType->isOffsetAccessible() ->and($otherType->hasOffsetValueType($this->offsetType)) ->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()), - [], ); return $result diff --git a/src/Type/Accessory/HasPropertyType.php b/src/Type/Accessory/HasPropertyType.php index 3378a7196db..c15bc7cd506 100644 --- a/src/Type/Accessory/HasPropertyType.php +++ b/src/Type/Accessory/HasPropertyType.php @@ -97,9 +97,8 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult return $type->isSubTypeOf($this); } - return new IsSuperTypeOfResult( + return IsSuperTypeOfResult::createFromTrinaryLogic( $type->hasInstanceProperty($this->propertyName)->or($type->hasStaticProperty($this->propertyName)), - [], ); } @@ -115,9 +114,8 @@ public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult $limit = TrinaryLogic::createMaybe(); } - return new IsSuperTypeOfResult( + return IsSuperTypeOfResult::createFromTrinaryLogic( $limit->and($otherType->hasInstanceProperty($this->propertyName)->or($otherType->hasStaticProperty($this->propertyName))), - [], ); } diff --git a/src/Type/Accessory/NonEmptyArrayType.php b/src/Type/Accessory/NonEmptyArrayType.php index d2d63ae97da..5fbddc82040 100644 --- a/src/Type/Accessory/NonEmptyArrayType.php +++ b/src/Type/Accessory/NonEmptyArrayType.php @@ -106,7 +106,7 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult return $type->isSubTypeOf($this); } - return new IsSuperTypeOfResult($type->isArray()->and($type->isIterableAtLeastOnce()), []); + return IsSuperTypeOfResult::createFromTrinaryLogic($type->isArray()->and($type->isIterableAtLeastOnce())); } public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult @@ -115,9 +115,8 @@ public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult return $otherType->isSuperTypeOf($this); } - return new IsSuperTypeOfResult( + return IsSuperTypeOfResult::createFromTrinaryLogic( $otherType->isArray()->and($otherType->isIterableAtLeastOnce())->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()), - [], ); } diff --git a/src/Type/Accessory/OversizedArrayType.php b/src/Type/Accessory/OversizedArrayType.php index 5805507e9f6..857ee75b186 100644 --- a/src/Type/Accessory/OversizedArrayType.php +++ b/src/Type/Accessory/OversizedArrayType.php @@ -94,7 +94,7 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult return $type->isSubTypeOf($this); } - return new IsSuperTypeOfResult($type->isArray()->and($type->isOversizedArray()), []); + return IsSuperTypeOfResult::createFromTrinaryLogic($type->isArray()->and($type->isOversizedArray())); } public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult @@ -103,9 +103,8 @@ public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult return $otherType->isSuperTypeOf($this); } - return new IsSuperTypeOfResult( + return IsSuperTypeOfResult::createFromTrinaryLogic( $otherType->isArray()->and($otherType->isOversizedArray())->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()), - [], ); } diff --git a/src/Type/CallableType.php b/src/Type/CallableType.php index 6ccf998b857..bc03b1ddb41 100644 --- a/src/Type/CallableType.php +++ b/src/Type/CallableType.php @@ -163,7 +163,7 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult private function isSuperTypeOfInternal(Type $type, bool $treatMixedAsAny, bool $strictTypes = true): IsSuperTypeOfResult { - $isCallable = new IsSuperTypeOfResult($type->isCallable(), []); + $isCallable = IsSuperTypeOfResult::createFromTrinaryLogic($type->isCallable()); if ($isCallable->no()) { return $isCallable; } @@ -180,7 +180,7 @@ private function isSuperTypeOfInternal(Type $type, bool $treatMixedAsAny, bool $ $typePure = $typePure->and($variant->isPure()); } - return $isCallable->and(new IsSuperTypeOfResult($typePure, [])); + return $isCallable->and(IsSuperTypeOfResult::createFromTrinaryLogic($typePure)); } return $isCallable; @@ -215,9 +215,8 @@ public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult return $otherType->isSuperTypeOf($this); } - return new IsSuperTypeOfResult( + return IsSuperTypeOfResult::createFromTrinaryLogic( $otherType->isCallable()->and($otherType instanceof self ? TrinaryLogic::createYes() : TrinaryLogic::createMaybe()), - [], ); } diff --git a/src/Type/CallableTypeHelper.php b/src/Type/CallableTypeHelper.php index 610112c9bc2..2b292914c95 100644 --- a/src/Type/CallableTypeHelper.php +++ b/src/Type/CallableTypeHelper.php @@ -111,16 +111,16 @@ public static function isParametersAcceptorSuperTypeOf( $pure = $ours->isPure(); if ($pure->yes()) { - $result = $result->and(new IsSuperTypeOfResult($theirs->isPure(), [])); + $result = $result->and(IsSuperTypeOfResult::createFromTrinaryLogic($theirs->isPure())); } elseif ($pure->no()) { - $result = $result->and(new IsSuperTypeOfResult($theirs->isPure()->negate(), [])); + $result = $result->and(IsSuperTypeOfResult::createFromTrinaryLogic($theirs->isPure()->negate())); } $ourStatic = $ours->isStaticClosure(); if ($ourStatic->yes()) { - $result = $result->and(new IsSuperTypeOfResult($theirs->isStaticClosure(), [])); + $result = $result->and(IsSuperTypeOfResult::createFromTrinaryLogic($theirs->isStaticClosure())); } elseif ($ourStatic->no()) { - $result = $result->and(new IsSuperTypeOfResult($theirs->isStaticClosure()->negate(), [])); + $result = $result->and(IsSuperTypeOfResult::createFromTrinaryLogic($theirs->isStaticClosure()->negate())); } return $result->and($isReturnTypeSuperType); diff --git a/src/Type/ClassStringType.php b/src/Type/ClassStringType.php index 58c550ce2f4..870b3ca3bdd 100644 --- a/src/Type/ClassStringType.php +++ b/src/Type/ClassStringType.php @@ -39,7 +39,7 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult return $type->isSubTypeOf($this); } - return new IsSuperTypeOfResult($type->isClassString(), []); + return IsSuperTypeOfResult::createFromTrinaryLogic($type->isClassString()); } public function isString(): TrinaryLogic diff --git a/src/Type/Constant/ConstantArrayType.php b/src/Type/Constant/ConstantArrayType.php index 338db40d8bd..85e802ecfb6 100644 --- a/src/Type/Constant/ConstantArrayType.php +++ b/src/Type/Constant/ConstantArrayType.php @@ -773,10 +773,10 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult if (count($this->keyTypes) === 0) { if (!$bothDefinite) { - return new IsSuperTypeOfResult($type->isIterableAtLeastOnce()->negate(), []); + return IsSuperTypeOfResult::createFromTrinaryLogic($type->isIterableAtLeastOnce()->negate()); } if ($thisUnsealedness->no()) { - return new IsSuperTypeOfResult($type->isIterableAtLeastOnce()->negate(), []); + return IsSuperTypeOfResult::createFromTrinaryLogic($type->isIterableAtLeastOnce()->negate()); } // $this is unsealed with no known keys — fall through to extras/unsealed-part checks below } diff --git a/src/Type/IsSuperTypeOfResult.php b/src/Type/IsSuperTypeOfResult.php index 557064936ee..3b626ec8e94 100644 --- a/src/Type/IsSuperTypeOfResult.php +++ b/src/Type/IsSuperTypeOfResult.php @@ -133,6 +133,34 @@ public static function createFromBoolean(bool $value): self return self::createNo(); } + /** + * The result without reasons - the shared instance of createYes(), createNo() or createMaybe(). + * + * @api + */ + public static function createFromTrinaryLogic(TrinaryLogic $result): self + { + if ($result->yes()) { + return self::createYes(); + } + if ($result->no()) { + return self::createNo(); + } + return self::createMaybe(); + } + + /** + * @param list $reasons + * @param list $lazyReasons + */ + private static function create(TrinaryLogic $result, array $reasons, array $lazyReasons): self + { + if ($reasons === [] && $lazyReasons === []) { + return self::createFromTrinaryLogic($result); + } + return new self($result, $reasons, $lazyReasons); + } + public function toAcceptsResult(): AcceptsResult { return new AcceptsResult($this->result, $this->getReasons()); @@ -145,11 +173,21 @@ public function and(self ...$others): self $lazyReasons = []; foreach ($others as $other) { $results[] = $other->result; - $reasons[] = $other->reasons; + if ($other->reasons !== []) { + $reasons[] = $other->reasons; + } + if ($other->lazyReasons === []) { + continue; + } + $lazyReasons[] = $other->lazyReasons; } - return new self( + if ($this->reasons === [] && $reasons === [] && $this->lazyReasons === [] && $lazyReasons === []) { + return self::createFromTrinaryLogic($this->result->and(...$results)); + } + + return self::create( $this->result->and(...$results), array_values(array_unique(array_merge($this->reasons, ...$reasons))), array_merge($this->lazyReasons, ...$lazyReasons), @@ -163,11 +201,21 @@ public function or(self ...$others): self $lazyReasons = []; foreach ($others as $other) { $results[] = $other->result; - $reasons[] = $other->reasons; + if ($other->reasons !== []) { + $reasons[] = $other->reasons; + } + if ($other->lazyReasons === []) { + continue; + } + $lazyReasons[] = $other->lazyReasons; } - return new self( + if ($this->reasons === [] && $reasons === [] && $this->lazyReasons === [] && $lazyReasons === []) { + return self::createFromTrinaryLogic($this->result->or(...$results)); + } + + return self::create( $this->result->or(...$results), array_values(array_unique(array_merge($this->reasons, ...$reasons))), array_merge($this->lazyReasons, ...$lazyReasons), @@ -187,7 +235,7 @@ public function decorateReasons(callable $cb): self $lazyReasons[] = static fn (): string => $cb($lazyReason()); } - return new self($this->result, $reasons, $lazyReasons); + return self::create($this->result, $reasons, $lazyReasons); } /** @see TrinaryLogic::extremeIdentity() */ @@ -210,7 +258,7 @@ public static function extremeIdentity(self ...$operands): self } } - return new self(TrinaryLogic::extremeIdentity(...$results), array_values(array_unique($reasons)), $lazyReasons); + return self::create(TrinaryLogic::extremeIdentity(...$results), array_values(array_unique($reasons)), $lazyReasons); } /** @see TrinaryLogic::maxMin() */ @@ -233,7 +281,7 @@ public static function maxMin(self ...$operands): self } } - return new self(TrinaryLogic::maxMin(...$results), array_values(array_unique($reasons)), $lazyReasons); + return self::create(TrinaryLogic::maxMin(...$results), array_values(array_unique($reasons)), $lazyReasons); } /** @@ -265,7 +313,7 @@ public static function lazyMaxMin( } } - return new self( + return self::create( $hasNo ? TrinaryLogic::createNo() : TrinaryLogic::createMaybe(), array_values(array_unique($reasons)), $lazyReasons, @@ -274,7 +322,7 @@ public static function lazyMaxMin( public function negate(): self { - return new self($this->result->negate(), $this->reasons, $this->lazyReasons); + return self::create($this->result->negate(), $this->reasons, $this->lazyReasons); } public function describe(): string diff --git a/src/Type/IterableType.php b/src/Type/IterableType.php index 9b445000179..6242ba64b15 100644 --- a/src/Type/IterableType.php +++ b/src/Type/IterableType.php @@ -103,14 +103,14 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult return $type->isSubTypeOf($this); } - return (new IsSuperTypeOfResult($type->isIterable(), [])) + return IsSuperTypeOfResult::createFromTrinaryLogic($type->isIterable()) ->and($this->getIterableValueType()->isSuperTypeOf($type->getIterableValueType())) ->and($this->getIterableKeyType()->isSuperTypeOf($type->getIterableKeyType())); } public function isSuperTypeOfMixed(Type $type): IsSuperTypeOfResult { - return (new IsSuperTypeOfResult($type->isIterable(), [])) + return IsSuperTypeOfResult::createFromTrinaryLogic($type->isIterable()) ->and($this->isNestedTypeSuperTypeOf($this->getIterableValueType(), $type->getIterableValueType())) ->and($this->isNestedTypeSuperTypeOf($this->getIterableKeyType(), $type->getIterableKeyType())); } @@ -153,7 +153,7 @@ public function isSubTypeOf(Type $otherType): IsSuperTypeOfResult } return $limit->and( - new IsSuperTypeOfResult($otherType->isIterable(), []), + IsSuperTypeOfResult::createFromTrinaryLogic($otherType->isIterable()), $otherType->getIterableValueType()->isSuperTypeOf($this->itemType), $otherType->getIterableKeyType()->isSuperTypeOf($this->keyType), ); diff --git a/src/Type/ObjectShapeType.php b/src/Type/ObjectShapeType.php index 1c61cd42997..fec23e94c59 100644 --- a/src/Type/ObjectShapeType.php +++ b/src/Type/ObjectShapeType.php @@ -359,7 +359,7 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult $result = $result->and($isSuperType); } - return $result->and(new IsSuperTypeOfResult($type->isObject(), [])); + return $result->and(IsSuperTypeOfResult::createFromTrinaryLogic($type->isObject())); } public function equals(Type $type): bool diff --git a/src/Type/ObjectType.php b/src/Type/ObjectType.php index 16a2ed918c4..139315d1c4c 100644 --- a/src/Type/ObjectType.php +++ b/src/Type/ObjectType.php @@ -604,7 +604,7 @@ public function isSuperTypeOf(Type $type): IsSuperTypeOfResult } if ($type instanceof ClosureType) { - return self::$superTypes[$thisDescription][$description] = new IsSuperTypeOfResult($this->isInstanceOf(Closure::class), []); + return self::$superTypes[$thisDescription][$description] = IsSuperTypeOfResult::createFromTrinaryLogic($this->isInstanceOf(Closure::class)); } if ($type instanceof ObjectWithoutClassType) { diff --git a/turbo-ext/src/AccessoryArrayListType.cpp b/turbo-ext/src/AccessoryArrayListType.cpp index d4c3801e133..22b94a2ae2c 100644 --- a/turbo-ext/src/AccessoryArrayListType.cpp +++ b/turbo-ext/src/AccessoryArrayListType.cpp @@ -55,7 +55,7 @@ class AccessoryArrayListType } zend_long isList = pt_type_op_trinary(Z_OBJ_P(type), PT_OP_IS_LIST, 0, NULL); if (UNEXPECTED(isList < 0)) return zv::Val(); - return pt_type_new_is_super_type_of_result(isList); + return pt_type_is_super_type_of_result(isList); } /* the union/intersection callback; yes for an AccessoryArrayListType; @@ -70,10 +70,10 @@ class AccessoryArrayListType ZVAL_OBJ(&selfZv, self); return pt_type_op(Z_OBJ_P(otherType), PT_OP_IS_SUPER_TYPE_OF, 1, &selfZv); } - if (instanceof_function(Z_OBJCE_P(otherType), pt_ce_accessory_array_list_type)) return pt_type_new_is_super_type_of_result(PT_TRI_YES); + if (instanceof_function(Z_OBJCE_P(otherType), pt_ce_accessory_array_list_type)) return pt_type_is_super_type_of_result(PT_TRI_YES); zend_long isList = pt_type_op_trinary(Z_OBJ_P(otherType), PT_OP_IS_LIST, 0, NULL); if (UNEXPECTED(isList < 0)) return zv::Val(); - return pt_type_new_is_super_type_of_result(pt_trinary_and(isList, PT_TRI_MAYBE)); + return pt_type_is_super_type_of_result(pt_trinary_and(isList, PT_TRI_MAYBE)); } /* $this->isSubTypeOf($acceptingType)->toAcceptsResult() */ diff --git a/turbo-ext/src/AccessoryDecimalIntegerStringType.cpp b/turbo-ext/src/AccessoryDecimalIntegerStringType.cpp index 8f69c2b7651..d09734a0d4c 100644 --- a/turbo-ext/src/AccessoryDecimalIntegerStringType.cpp +++ b/turbo-ext/src/AccessoryDecimalIntegerStringType.cpp @@ -97,7 +97,7 @@ class AccessoryDecimalIntegerStringType if (UNEXPECTED(isString < 0)) return zv::Val(); bool inverse = false; if (UNEXPECTED(!this->inverse(inverse))) return zv::Val(); - return pt_type_new_is_super_type_of_result(pt_trinary_and(isString, inverse ? trinaryNegate(isDecimalIntegerString) : isDecimalIntegerString)); + return pt_type_is_super_type_of_result(pt_trinary_and(isString, inverse ? trinaryNegate(isDecimalIntegerString) : isDecimalIntegerString)); } /* the union/intersection callback; yes for a numeric, lowercase or @@ -134,7 +134,7 @@ class AccessoryDecimalIntegerStringType ZVAL_OBJ(&selfZv, self); zv::Val equal = pt_type_op(Z_OBJ_P(otherType), PT_OP_EQUALS, 1, &selfZv); if (UNEXPECTED(equal.isUndef())) return zv::Val(); - return pt_type_new_is_super_type_of_result(pt_trinary_and(otherTypeResult, zend_is_true(equal.raw()) ? PT_TRI_YES : PT_TRI_MAYBE)); + return pt_type_is_super_type_of_result(pt_trinary_and(otherTypeResult, zend_is_true(equal.raw()) ? PT_TRI_YES : PT_TRI_MAYBE)); } /* $this->isSubTypeOf($acceptingType)->toAcceptsResult() */ diff --git a/turbo-ext/src/AccessoryLiteralStringType.cpp b/turbo-ext/src/AccessoryLiteralStringType.cpp index 7528f7f4e2c..976e46fab5c 100644 --- a/turbo-ext/src/AccessoryLiteralStringType.cpp +++ b/turbo-ext/src/AccessoryLiteralStringType.cpp @@ -57,7 +57,7 @@ class AccessoryLiteralStringType if (equal) return pt_type_is_super_type_of_result(PT_TRI_YES); zend_long isLiteralString = pt_type_call_trinary(Z_OBJ_P(type), PT_LC("isliteralstring"), 0, NULL); if (UNEXPECTED(isLiteralString < 0)) return zv::Val(); - return pt_type_new_is_super_type_of_result(isLiteralString); + return pt_type_is_super_type_of_result(isLiteralString); } /* the union/intersection callback; else the other type's literal-string @@ -77,7 +77,7 @@ class AccessoryLiteralStringType if (!instanceof_function(Z_OBJCE_P(otherType), pt_ce_accessory_literal_string_type)) { value = pt_trinary_and(value, PT_TRI_MAYBE); } - return pt_type_new_is_super_type_of_result(value); + return pt_type_is_super_type_of_result(value); } /* $this->isSubTypeOf($acceptingType)->toAcceptsResult() */ diff --git a/turbo-ext/src/AccessoryLowercaseStringType.cpp b/turbo-ext/src/AccessoryLowercaseStringType.cpp index 5d2827f6266..7808c1dfb43 100644 --- a/turbo-ext/src/AccessoryLowercaseStringType.cpp +++ b/turbo-ext/src/AccessoryLowercaseStringType.cpp @@ -56,7 +56,7 @@ class AccessoryLowercaseStringType if (equal) return pt_type_is_super_type_of_result(PT_TRI_YES); zend_long isLowercaseString = pt_type_call_trinary(Z_OBJ_P(type), PT_LC("islowercasestring"), 0, NULL); if (UNEXPECTED(isLowercaseString < 0)) return zv::Val(); - return pt_type_new_is_super_type_of_result(isLowercaseString); + return pt_type_is_super_type_of_result(isLowercaseString); } /* the union/intersection callback; else the other type's @@ -76,7 +76,7 @@ class AccessoryLowercaseStringType if (!instanceof_function(Z_OBJCE_P(otherType), pt_ce_accessory_lowercase_string_type)) { value = pt_trinary_and(value, PT_TRI_MAYBE); } - return pt_type_new_is_super_type_of_result(value); + return pt_type_is_super_type_of_result(value); } /* $this->isSubTypeOf($acceptingType)->toAcceptsResult() */ diff --git a/turbo-ext/src/AccessoryNonEmptyStringType.cpp b/turbo-ext/src/AccessoryNonEmptyStringType.cpp index f372582e333..91519b8945d 100644 --- a/turbo-ext/src/AccessoryNonEmptyStringType.cpp +++ b/turbo-ext/src/AccessoryNonEmptyStringType.cpp @@ -59,7 +59,7 @@ class AccessoryNonEmptyStringType if (isNonFalsyString == PT_TRI_YES) return pt_type_is_super_type_of_result(PT_TRI_YES); zend_long isNonEmptyString = pt_type_call_trinary(Z_OBJ_P(type), PT_LC("isnonemptystring"), 0, NULL); if (UNEXPECTED(isNonEmptyString < 0)) return zv::Val(); - return pt_type_new_is_super_type_of_result(isNonEmptyString); + return pt_type_is_super_type_of_result(isNonEmptyString); } /* the union/intersection callback; else the other type's @@ -79,7 +79,7 @@ class AccessoryNonEmptyStringType if (!instanceof_function(Z_OBJCE_P(otherType), pt_ce_accessory_non_empty_string_type)) { value = pt_trinary_and(value, PT_TRI_MAYBE); } - return pt_type_new_is_super_type_of_result(value); + return pt_type_is_super_type_of_result(value); } /* $this->isSubTypeOf($acceptingType)->toAcceptsResult() */ diff --git a/turbo-ext/src/AccessoryNonFalsyStringType.cpp b/turbo-ext/src/AccessoryNonFalsyStringType.cpp index 3f8a29ac1f5..237c790a851 100644 --- a/turbo-ext/src/AccessoryNonFalsyStringType.cpp +++ b/turbo-ext/src/AccessoryNonFalsyStringType.cpp @@ -56,7 +56,7 @@ class AccessoryNonFalsyStringType if (equal) return pt_type_is_super_type_of_result(PT_TRI_YES); zend_long isNonFalsyString = pt_type_call_trinary(Z_OBJ_P(type), PT_LC("isnonfalsystring"), 0, NULL); if (UNEXPECTED(isNonFalsyString < 0)) return zv::Val(); - return pt_type_new_is_super_type_of_result(isNonFalsyString); + return pt_type_is_super_type_of_result(isNonFalsyString); } /* the union/intersection callback; yes for an AccessoryNonEmptyStringType; @@ -78,7 +78,7 @@ class AccessoryNonFalsyStringType if (!instanceof_function(Z_OBJCE_P(otherType), pt_ce_accessory_non_falsy_string_type)) { value = pt_trinary_and(value, PT_TRI_MAYBE); } - return pt_type_new_is_super_type_of_result(value); + return pt_type_is_super_type_of_result(value); } /* $this->isSubTypeOf($acceptingType)->toAcceptsResult() */ diff --git a/turbo-ext/src/AccessoryNumericStringType.cpp b/turbo-ext/src/AccessoryNumericStringType.cpp index 65e552cc7ea..8d87a91dbd7 100644 --- a/turbo-ext/src/AccessoryNumericStringType.cpp +++ b/turbo-ext/src/AccessoryNumericStringType.cpp @@ -56,7 +56,7 @@ class AccessoryNumericStringType if (equal) return pt_type_is_super_type_of_result(PT_TRI_YES); zend_long isNumericString = pt_type_call_trinary(Z_OBJ_P(type), PT_LC("isnumericstring"), 0, NULL); if (UNEXPECTED(isNumericString < 0)) return zv::Val(); - return pt_type_new_is_super_type_of_result(isNumericString); + return pt_type_is_super_type_of_result(isNumericString); } /* the union/intersection callback; else the other type's numeric-string @@ -76,7 +76,7 @@ class AccessoryNumericStringType if (!instanceof_function(Z_OBJCE_P(otherType), pt_ce_accessory_numeric_string_type)) { value = pt_trinary_and(value, PT_TRI_MAYBE); } - return pt_type_new_is_super_type_of_result(value); + return pt_type_is_super_type_of_result(value); } /* $this->isSubTypeOf($acceptingType)->toAcceptsResult() */ diff --git a/turbo-ext/src/AccessoryUppercaseStringType.cpp b/turbo-ext/src/AccessoryUppercaseStringType.cpp index 7717a970f52..3be02f97c47 100644 --- a/turbo-ext/src/AccessoryUppercaseStringType.cpp +++ b/turbo-ext/src/AccessoryUppercaseStringType.cpp @@ -56,7 +56,7 @@ class AccessoryUppercaseStringType if (equal) return pt_type_is_super_type_of_result(PT_TRI_YES); zend_long isUppercaseString = pt_type_call_trinary(Z_OBJ_P(type), PT_LC("isuppercasestring"), 0, NULL); if (UNEXPECTED(isUppercaseString < 0)) return zv::Val(); - return pt_type_new_is_super_type_of_result(isUppercaseString); + return pt_type_is_super_type_of_result(isUppercaseString); } /* the union/intersection callback; else the other type's @@ -76,7 +76,7 @@ class AccessoryUppercaseStringType if (!instanceof_function(Z_OBJCE_P(otherType), pt_ce_accessory_uppercase_string_type)) { value = pt_trinary_and(value, PT_TRI_MAYBE); } - return pt_type_new_is_super_type_of_result(value); + return pt_type_is_super_type_of_result(value); } /* $this->isSubTypeOf($acceptingType)->toAcceptsResult() */ diff --git a/turbo-ext/src/CallableType.cpp b/turbo-ext/src/CallableType.cpp index 5a4cd646e46..d693db903a7 100644 --- a/turbo-ext/src/CallableType.cpp +++ b/turbo-ext/src/CallableType.cpp @@ -202,7 +202,7 @@ class CallableType /* TrinaryLogic::and(): the minimum */ typePure = variantPure < typePure ? variantPure : typePure; } - zv::Val pureResult = pt_type_new_is_super_type_of_result(typePure); + zv::Val pureResult = pt_type_is_super_type_of_result(typePure); if (UNEXPECTED(pureResult.isUndef())) return zv::Val(); return pt_type_op(Z_OBJ_P(isCallable.raw()), PT_OP_AND, 1, pureResult.raw()); } @@ -264,7 +264,7 @@ class CallableType if (UNEXPECTED(callable < 0)) return zv::Val(); /* ->and($otherType instanceof self ? yes : maybe): the minimum */ zend_long limit = instanceof_function(Z_OBJCE_P(otherType), pt_ce_callable_type) ? PT_TRI_YES : PT_TRI_MAYBE; - return pt_type_new_is_super_type_of_result(callable < limit ? callable : limit); + return pt_type_is_super_type_of_result(callable < limit ? callable : limit); } /* $this->isSubTypeOf($acceptingType)->toAcceptsResult() */ diff --git a/turbo-ext/src/CallableTypeHelper.cpp b/turbo-ext/src/CallableTypeHelper.cpp index 67ce5f5a6a0..c78d5a30c79 100644 --- a/turbo-ext/src/CallableTypeHelper.cpp +++ b/turbo-ext/src/CallableTypeHelper.cpp @@ -193,7 +193,7 @@ class CallableTypeHelper } private: - /* $result = $result->and(new IsSuperTypeOfResult($theirs->probe()[->negate()], [])) + /* $result = $result->and(IsSuperTypeOfResult::createFromTrinaryLogic($theirs->probe()[->negate()])) * when $ours->probe() is yes / no; false = pending exception */ [[nodiscard]] static bool andTrinaryProbe(zv::Val &result, zval *ours, zval *theirs, const char *lcname, size_t len) { diff --git a/turbo-ext/src/ClassStringType.cpp b/turbo-ext/src/ClassStringType.cpp index f7e73c681a2..c7d2fba8103 100644 --- a/turbo-ext/src/ClassStringType.cpp +++ b/turbo-ext/src/ClassStringType.cpp @@ -47,7 +47,7 @@ class ClassStringType return pt_type_accepts_result(isClassString); } - /* the CompoundType callback, else new IsSuperTypeOfResult($type->isClassString(), []); + /* the CompoundType callback, else IsSuperTypeOfResult::createFromTrinaryLogic($type->isClassString()); * UNDEF = pending exception */ zv::Val isSuperTypeOf(zval *type) const { diff --git a/turbo-ext/src/ConstantArrayType.cpp b/turbo-ext/src/ConstantArrayType.cpp index 3caf61d12a9..4ed1a935276 100644 --- a/turbo-ext/src/ConstantArrayType.cpp +++ b/turbo-ext/src/ConstantArrayType.cpp @@ -1788,7 +1788,7 @@ class ConstantArrayType if (!bothDefinite || thisUnsealedness == PT_TRI_NO) { zend_long atLeastOnce = pt_type_op_trinary(Z_OBJ_P(type), PT_OP_IS_ITERABLE_AT_LEAST_ONCE, 0, NULL); if (UNEXPECTED(atLeastOnce < 0)) return zv::Val(); - return pt_type_new_is_super_type_of_result(trinaryNegate(atLeastOnce)); + return pt_type_is_super_type_of_result(trinaryNegate(atLeastOnce)); } /* $this is unsealed with no known keys — fall through to extras/unsealed-part checks below */ } diff --git a/turbo-ext/src/HasMethodType.cpp b/turbo-ext/src/HasMethodType.cpp index ac3a2f7feb2..b24a0adecdf 100644 --- a/turbo-ext/src/HasMethodType.cpp +++ b/turbo-ext/src/HasMethodType.cpp @@ -90,7 +90,7 @@ class HasMethodType } zend_long has = otherHasMethod(type); if (UNEXPECTED(has < 0)) return zv::Val(); - return pt_type_new_is_super_type_of_result(has); + return pt_type_is_super_type_of_result(has); } /* the union/intersection callback; yes for a callable other type when @@ -128,7 +128,7 @@ class HasMethodType zend_long limit = instanceof_function(Z_OBJCE_P(otherType), pt_ce_has_method_type) ? PT_TRI_YES : PT_TRI_MAYBE; zend_long has = otherHasMethod(otherType); if (UNEXPECTED(has < 0)) return zv::Val(); - return pt_type_new_is_super_type_of_result(pt_trinary_and(limit, has)); + return pt_type_is_super_type_of_result(pt_trinary_and(limit, has)); } /* $this->isSubTypeOf($acceptingType)->toAcceptsResult() */ diff --git a/turbo-ext/src/HasOffsetType.cpp b/turbo-ext/src/HasOffsetType.cpp index a2390d65ef9..73dcefdf4f3 100644 --- a/turbo-ext/src/HasOffsetType.cpp +++ b/turbo-ext/src/HasOffsetType.cpp @@ -105,7 +105,7 @@ class HasOffsetType if (equal) return pt_type_is_super_type_of_result(PT_TRI_YES); zend_long value = accessibleAndHasOffset(type); if (UNEXPECTED(value < 0)) return zv::Val(); - return pt_type_new_is_super_type_of_result(value); + return pt_type_is_super_type_of_result(value); } /* the union/intersection callback; else the other type's @@ -125,7 +125,7 @@ class HasOffsetType if (!instanceof_function(Z_OBJCE_P(otherType), pt_ce_has_offset_type)) { value = pt_trinary_and(value, PT_TRI_MAYBE); } - return pt_type_new_is_super_type_of_result(value); + return pt_type_is_super_type_of_result(value); } /* $this->isSubTypeOf($acceptingType)->toAcceptsResult() */ diff --git a/turbo-ext/src/HasOffsetValueType.cpp b/turbo-ext/src/HasOffsetValueType.cpp index d2834f97a1b..7c23210570b 100644 --- a/turbo-ext/src/HasOffsetValueType.cpp +++ b/turbo-ext/src/HasOffsetValueType.cpp @@ -139,7 +139,7 @@ class HasOffsetValueType if (equal) return pt_type_is_super_type_of_result(PT_TRI_YES); zend_long value = accessibleAndHasOffset(type); if (UNEXPECTED(value < 0)) return zv::Val(); - zv::Val result = pt_type_new_is_super_type_of_result(value); + zv::Val result = pt_type_is_super_type_of_result(value); if (UNEXPECTED(result.isUndef())) return zv::Val(); zv::Val offsetValue = offsetValueTypeOf(type); if (UNEXPECTED(offsetValue.isUndef())) return zv::Val(); @@ -168,7 +168,7 @@ class HasOffsetValueType if (!instanceof_function(Z_OBJCE_P(otherType), pt_ce_has_offset_value_type)) { value = pt_trinary_and(value, PT_TRI_MAYBE); } - zv::Val result = pt_type_new_is_super_type_of_result(value); + zv::Val result = pt_type_is_super_type_of_result(value); if (UNEXPECTED(result.isUndef())) return zv::Val(); zv::Val offsetValue = offsetValueTypeOf(otherType); if (UNEXPECTED(offsetValue.isUndef())) return zv::Val(); diff --git a/turbo-ext/src/HasPropertyType.cpp b/turbo-ext/src/HasPropertyType.cpp index c056469feeb..f48f77b0a8c 100644 --- a/turbo-ext/src/HasPropertyType.cpp +++ b/turbo-ext/src/HasPropertyType.cpp @@ -97,7 +97,7 @@ class HasPropertyType } zend_long has = otherHasProperty(type); if (UNEXPECTED(has < 0)) return zv::Val(); - return pt_type_new_is_super_type_of_result(has); + return pt_type_is_super_type_of_result(has); } /* the union/intersection callback; else the other type's @@ -115,7 +115,7 @@ class HasPropertyType zend_long limit = instanceof_function(Z_OBJCE_P(otherType), pt_ce_has_property_type) ? PT_TRI_YES : PT_TRI_MAYBE; zend_long has = otherHasProperty(otherType); if (UNEXPECTED(has < 0)) return zv::Val(); - return pt_type_new_is_super_type_of_result(pt_trinary_and(limit, has)); + return pt_type_is_super_type_of_result(pt_trinary_and(limit, has)); } /* $this->isSubTypeOf($acceptingType)->toAcceptsResult() */ diff --git a/turbo-ext/src/IsSuperTypeOfResult.cpp b/turbo-ext/src/IsSuperTypeOfResult.cpp index 76b682a3d45..31227faeb86 100644 --- a/turbo-ext/src/IsSuperTypeOfResult.cpp +++ b/turbo-ext/src/IsSuperTypeOfResult.cpp @@ -154,6 +154,15 @@ class IsSuperTypeOfResult static zv::Val createFromBoolean(bool value) { return value ? createYes() : createNo(NULL, NULL); } + /* the createYes() / createNo() / createMaybe() singleton of a + * TrinaryLogic; UNDEF = pending exception */ + static zv::Val createFromTrinaryLogic(zval *trinary) + { + zend_long value = pt_type_trinary_value(trinary); + if (UNEXPECTED(value < 0)) return zv::Val(); + return singleton(value); + } + /* new AcceptsResult($this->result, $this->getReasons()) — always a fresh * instance; UNDEF = pending exception */ zv::Val toAcceptsResult() const @@ -188,8 +197,9 @@ class IsSuperTypeOfResult zv::Val decoratedLazy = wrapLazyReasons(zv::ArrRef(lazyReasons), zv::Ref(&fci->function_name)); if (UNEXPECTED(decoratedLazy.isUndef())) return zv::Val(); - if (UNEXPECTED(resultValue() < 0)) return zv::Val(); - return create(OBJ_PROP_NUM(self, PT_RESULT_PROP_RESULT), std::move(decorated), std::move(decoratedLazy)); + zend_long value = resultValue(); + if (UNEXPECTED(value < 0)) return zv::Val(); + return fromParts(value, std::move(decorated), std::move(decoratedLazy)); } /* count >= 1 (the glue throws for none); UNDEF = pending exception */ @@ -246,8 +256,7 @@ class IsSuperTypeOfResult return zv::Val(); } } - /* new self(...) — a fresh instance, not the singleton, like the twin */ - return create(pt_trinary_singleton(hasNo ? PT_TRI_NO : PT_TRI_MAYBE), zv::Val::adopt(reasons), zv::Val::adopt(lazyReasons)); + return fromParts(hasNo ? PT_TRI_NO : PT_TRI_MAYBE, zv::Val::adopt(reasons), zv::Val::adopt(lazyReasons)); } /* UNDEF = pending exception */ @@ -259,7 +268,7 @@ class IsSuperTypeOfResult if (UNEXPECTED(reasons == NULL)) return zv::Val(); zval *lazyReasons = pt_result_array_slot(self, slots::lazyReasons, "lazyReasons"); if (UNEXPECTED(lazyReasons == NULL)) return zv::Val(); - return create(pt_trinary_singleton(pt_trinary_negate_value(value)), zv::Val::copyOf(zv::Ref(reasons)), zv::Val::copyOf(zv::Ref(lazyReasons))); + return fromParts(pt_trinary_negate_value(value), zv::Val::copyOf(zv::Ref(reasons)), zv::Val::copyOf(zv::Ref(lazyReasons))); } /* NULL = pending exception */ @@ -355,6 +364,27 @@ class IsSuperTypeOfResult return zv::Val::copyOf(zv::Ref(array)); } + /* the twin's private create(): the singleton when there are neither + * reasons nor lazy reasons, new self(...) otherwise; the arrays are + * consumed; UNDEF = pending exception */ + static zv::Val fromParts(zend_long value, zv::Val reasons, zv::Val lazyReasons) + { + if (zend_hash_num_elements(Z_ARRVAL_P(reasons.raw())) == 0 && zend_hash_num_elements(Z_ARRVAL_P(lazyReasons.raw())) == 0) return singleton(value); + return create(pt_trinary_singleton(value), std::move(reasons), std::move(lazyReasons)); + } + + /* whether a result carries reasons or lazy reasons; false = pending + * exception */ + [[nodiscard]] static bool hasReasons(zend_object *result, bool &out) + { + zval *reasons = pt_result_array_slot(result, PT_RESULT_PROP_REASONS, "reasons"); + if (UNEXPECTED(reasons == NULL)) return false; + zval *lazyReasons = pt_result_array_slot(result, slots::lazyReasons, "lazyReasons"); + if (UNEXPECTED(lazyReasons == NULL)) return false; + out = out || zend_hash_num_elements(Z_ARRVAL_P(reasons)) > 0 || zend_hash_num_elements(Z_ARRVAL_P(lazyReasons)) > 0; + return true; + } + /* and()/or(): the trinary fold, the merged and deduplicated reasons, the * merged lazy reasons */ zv::Val combine(zval *others, uint32_t count, bool isAnd) const @@ -363,6 +393,13 @@ class IsSuperTypeOfResult if (UNEXPECTED(value < 0)) return zv::Val(); zend_long folded = isAnd ? pt_result_and(value, others, count) : pt_result_or(value, others, count); if (UNEXPECTED(folded < 0)) return zv::Val(); + /* no operand has reasons: the shared instance, nothing to merge */ + bool anyReasons = false; + if (UNEXPECTED(!hasReasons(self, anyReasons))) return zv::Val(); + for (uint32_t i = 0; i < count && !anyReasons; i++) { + if (UNEXPECTED(!hasReasons(Z_OBJ_P(zv::Ref(&others[i]).deref().raw()), anyReasons))) return zv::Val(); + } + if (!anyReasons) return singleton(folded); zval reasons; if (UNEXPECTED(!pt_reasons_merge_operands(&reasons, self, others, count, PT_RESULT_PROP_REASONS, true, true))) return zv::Val(); zval lazyReasons; @@ -370,7 +407,7 @@ class IsSuperTypeOfResult zval_ptr_dtor(&reasons); return zv::Val(); } - return create(pt_trinary_singleton(folded), zv::Val::adopt(reasons), zv::Val::adopt(lazyReasons)); + return fromParts(folded, zv::Val::adopt(reasons), zv::Val::adopt(lazyReasons)); } /* extremeIdentity()/maxMin(): a folded value plus the operands' reasons @@ -385,7 +422,7 @@ class IsSuperTypeOfResult zval_ptr_dtor(&reasons); return zv::Val(); } - return create(pt_trinary_singleton(folded), zv::Val::adopt(reasons), zv::Val::adopt(lazyReasons)); + return fromParts(folded, zv::Val::adopt(reasons), zv::Val::adopt(lazyReasons)); } /* array_map(static fn (Closure $cb): string => $cb(), $lazyReasons): @@ -639,6 +676,14 @@ PT_MINIT_REGISTRATION(pt_register_is_super_type_of_result) result.intoReturnValue(return_value); }); + cls.method(sigs::createFromTrinaryLogic, [](INTERNAL_FUNCTION_PARAMETERS) { + zval *result; + if (!zp::parse(execute_data, result)) RETURN_THROWS(); + zv::Val created = IsSuperTypeOfResult::createFromTrinaryLogic(result); + if (UNEXPECTED(created.isUndef())) RETURN_THROWS(); + created.intoReturnValue(return_value); + }); + cls.method(sigs::toAcceptsResult, [](INTERNAL_FUNCTION_PARAMETERS) { ZEND_PARSE_PARAMETERS_NONE(); zv::Val result = IsSuperTypeOfResult(Z_OBJ_P(ZEND_THIS)).toAcceptsResult(); diff --git a/turbo-ext/src/IterableType.cpp b/turbo-ext/src/IterableType.cpp index 63121b2bda5..d5db027563a 100644 --- a/turbo-ext/src/IterableType.cpp +++ b/turbo-ext/src/IterableType.cpp @@ -153,7 +153,7 @@ class IterableType /* the same with the nested mixed types compared by explicitness */ zv::Val isSuperTypeOfMixed(zval *type) const { return isSuperTypeOfNested(type, true); } - /* (new IsSuperTypeOfResult($type->isIterable(), [])) + /* IsSuperTypeOfResult::createFromTrinaryLogic($type->isIterable()) * ->and()->and(), the nested comparisons * isSuperTypeOf() or isNestedTypeSuperTypeOf(); UNDEF = pending exception */ zv::Val isSuperTypeOfNested(zval *type, bool nested) const diff --git a/turbo-ext/src/NonEmptyArrayType.cpp b/turbo-ext/src/NonEmptyArrayType.cpp index 528c6668dc4..0b5f26c463c 100644 --- a/turbo-ext/src/NonEmptyArrayType.cpp +++ b/turbo-ext/src/NonEmptyArrayType.cpp @@ -55,7 +55,7 @@ class NonEmptyArrayType } zend_long value = arrayAndAtLeastOnce(type); if (UNEXPECTED(value < 0)) return zv::Val(); - return pt_type_new_is_super_type_of_result(value); + return pt_type_is_super_type_of_result(value); } /* the union/intersection callback; else the other type's @@ -75,7 +75,7 @@ class NonEmptyArrayType if (!instanceof_function(Z_OBJCE_P(otherType), pt_ce_non_empty_array_type)) { value = pt_trinary_and(value, PT_TRI_MAYBE); } - return pt_type_new_is_super_type_of_result(value); + return pt_type_is_super_type_of_result(value); } /* $this->isSubTypeOf($acceptingType)->toAcceptsResult() */ diff --git a/turbo-ext/src/ObjectShapeType.cpp b/turbo-ext/src/ObjectShapeType.cpp index 97c48c5b96f..56af57bd345 100644 --- a/turbo-ext/src/ObjectShapeType.cpp +++ b/turbo-ext/src/ObjectShapeType.cpp @@ -386,13 +386,10 @@ class ObjectShapeType if (UNEXPECTED(result.isUndef())) return zv::Val(); } - /* $result->and(new IsSuperTypeOfResult($type->isObject(), [])) */ + /* $result->and(IsSuperTypeOfResult::createFromTrinaryLogic($type->isObject())) */ zv::Val isObject = pt_type_call(Z_OBJ_P(type), PT_LC("isobject"), 0, NULL); if (UNEXPECTED(isObject.isUndef())) return zv::Val(); - zval args[2]; - ZVAL_COPY_VALUE(&args[0], isObject.raw()); - ZVAL_EMPTY_ARRAY(&args[1]); - zv::Val objectResult = pt_type_new_ce(pt_ce_is_super_type_of_result, 2, args); + zv::Val objectResult = pt_callable_is_super_type_of_result_of(isObject.raw()); if (UNEXPECTED(objectResult.isUndef())) return zv::Val(); return resultAnd(std::move(result), objectResult.raw()); } diff --git a/turbo-ext/src/ObjectType.cpp b/turbo-ext/src/ObjectType.cpp index 37587a5e1d9..c940f3814a2 100644 --- a/turbo-ext/src/ObjectType.cpp +++ b/turbo-ext/src/ObjectType.cpp @@ -940,17 +940,10 @@ class ObjectType bool isClosure; if (UNEXPECTED(!pt_type_instanceof_ce(type, pt_ce_closure_type, isClosure))) return zv::Val(); if (isClosure) { - /* new IsSuperTypeOfResult($this->isInstanceOf(Closure::class), []) */ + /* IsSuperTypeOfResult::createFromTrinaryLogic($this->isInstanceOf(Closure::class)) */ zend_long isInstance = thisIsInstanceOfLiteral(PT_LC("Closure")); if (UNEXPECTED(isInstance < 0)) return zv::Val(); - zval reasons, lazyReasons; - ZVAL_EMPTY_ARRAY(&reasons); - ZVAL_EMPTY_ARRAY(&lazyReasons); /* the constructor's default */ - zval result; - if (UNEXPECTED(!pt_result_object_create(&result, pt_ce_is_super_type_of_result, pt_trinary_singleton(isInstance), &reasons, &lazyReasons))) { - return zv::Val(); - } - return storeSuperType(thisDescriptionStr, descriptionStr, zv::Val::adopt(result)); + return storeSuperType(thisDescriptionStr, descriptionStr, pt_type_is_super_type_of_result(isInstance)); } if (isObjectWithoutClass) { diff --git a/turbo-ext/src/OversizedArrayType.cpp b/turbo-ext/src/OversizedArrayType.cpp index b0a6fb37a5a..8b44193079b 100644 --- a/turbo-ext/src/OversizedArrayType.cpp +++ b/turbo-ext/src/OversizedArrayType.cpp @@ -53,7 +53,7 @@ class OversizedArrayType } zend_long value = arrayAnd(type, PT_LC("isoversizedarray")); if (UNEXPECTED(value < 0)) return zv::Val(); - return pt_type_new_is_super_type_of_result(value); + return pt_type_is_super_type_of_result(value); } /* the union/intersection callback; else the other type's @@ -73,7 +73,7 @@ class OversizedArrayType if (!instanceof_function(Z_OBJCE_P(otherType), pt_ce_oversized_array_type)) { value = pt_trinary_and(value, PT_TRI_MAYBE); } - return pt_type_new_is_super_type_of_result(value); + return pt_type_is_super_type_of_result(value); } /* $this->isSubTypeOf($acceptingType)->toAcceptsResult() */ diff --git a/turbo-ext/src/TypeTraits.cpp b/turbo-ext/src/TypeTraits.cpp index c5f9ddd13b5..6272c721393 100644 --- a/turbo-ext/src/TypeTraits.cpp +++ b/turbo-ext/src/TypeTraits.cpp @@ -2142,16 +2142,6 @@ zval *pt_type_native_callback_state(zval *callback, int index) return OBJ_PROP_NUM(Z_OBJ_P(callback), index == 0 ? PT_NC_PROP_STATE0 : PT_NC_PROP_STATE1); } -zv::Val pt_type_new_is_super_type_of_result(zend_long value) -{ - zval reasons, lazyReasons; - ZVAL_EMPTY_ARRAY(&reasons); - ZVAL_EMPTY_ARRAY(&lazyReasons); /* the constructor's default [] */ - zval result; - if (UNEXPECTED(!pt_result_object_create(&result, pt_ce_is_super_type_of_result, pt_trinary_singleton(value), &reasons, &lazyReasons))) return zv::Val(); - return zv::Val::adopt(result); -} - zv::Val pt_type_new_accepts_result(zend_long value) { zval reasons; @@ -3304,12 +3294,9 @@ zv::Val pt_callable_traverse_parameters_simultaneously(zval *leftParameters, zva zv::Val pt_callable_is_super_type_of_result_of(zval *trinary) { - zval reasons, lazyReasons; - ZVAL_EMPTY_ARRAY(&reasons); - ZVAL_EMPTY_ARRAY(&lazyReasons); /* the constructor's default [] */ - zval result; - if (UNEXPECTED(!pt_result_object_create(&result, pt_ce_is_super_type_of_result, trinary, &reasons, &lazyReasons))) return zv::Val(); - return zv::Val::adopt(result); + zend_long value = pt_type_trinary_value(trinary); + if (UNEXPECTED(value < 0)) return zv::Val(); + return pt_type_is_super_type_of_result(value); } zv::Val pt_callable_out_of_class_scope() diff --git a/turbo-ext/src/TypeTraits.h b/turbo-ext/src/TypeTraits.h index 710bffca6d3..7320a598db5 100644 --- a/turbo-ext/src/TypeTraits.h +++ b/turbo-ext/src/TypeTraits.h @@ -505,10 +505,9 @@ zv::Val pt_type_native_callback(pt_native_callback fn, zval *state0, zval *state /* the holder's state slot (0 or 1), for reading a by-reference `use` back * after the call; borrowed */ zval *pt_type_native_callback_state(zval *callback, int index); -/* new IsSuperTypeOfResult($trinary, []) / new AcceptsResult($trinary, []) - * for a PT_TRI_* value — fresh instances, as the accessories' `new` spells - * them (not the create*() singletons); UNDEF = pending exception */ -zv::Val pt_type_new_is_super_type_of_result(zend_long value); +/* new AcceptsResult($trinary, []) for a PT_TRI_* value — a fresh instance, + * as the accessories' `new` spells it (not the create*() singletons); + * UNDEF = pending exception */ zv::Val pt_type_new_accepts_result(zend_long value); /* $result->and($other) on two result objects, natively for two * AcceptsResults; UNDEF = pending exception (also for an UNDEF $result) */ @@ -664,8 +663,8 @@ zv::Val pt_callable_traverse_parameters(zval *parameters, zend_fcall_info *fci, /* the traverseSimultaneously() parameter mapping over the left and right * parameter lists of equal size; UNDEF = pending exception */ zv::Val pt_callable_traverse_parameters_simultaneously(zval *leftParameters, zval *rightParameters, zend_fcall_info *fci, zend_fcall_info_cache *fcc); -/* new IsSuperTypeOfResult($trinary, []) over a TrinaryLogic zval; UNDEF = - * pending exception */ +/* IsSuperTypeOfResult::createFromTrinaryLogic($trinary) over a TrinaryLogic + * zval; UNDEF = pending exception */ zv::Val pt_callable_is_super_type_of_result_of(zval *trinary); /* new OutOfClassScope(); UNDEF = pending exception */ zv::Val pt_callable_out_of_class_scope(); diff --git a/turbo-ext/src/generated/IsSuperTypeOfResult.h b/turbo-ext/src/generated/IsSuperTypeOfResult.h index 7b62e1ba88d..433934e9fa6 100644 --- a/turbo-ext/src/generated/IsSuperTypeOfResult.h +++ b/turbo-ext/src/generated/IsSuperTypeOfResult.h @@ -51,21 +51,23 @@ inline constexpr char strings[] = "createMaybe\0" /* 140 */ "value\0" /* 152 */ "createFromBoolean\0" /* 158 */ - "PHPStan\\Type\\AcceptsResult\0" /* 176 */ - "toAcceptsResult\0" /* 203 */ - "others\0" /* 219 */ - "and\0" /* 226 */ - "or\0" /* 230 */ - "cb\0" /* 233 */ - "decorateReasons\0" /* 236 */ - "operands\0" /* 252 */ - "extremeIdentity\0" /* 261 */ - "maxMin\0" /* 277 */ - "objects\0" /* 284 */ - "callback\0" /* 292 */ - "lazyMaxMin\0" /* 301 */ - "negate\0" /* 312 */ - "describe"; /* 319 */ + "createFromTrinaryLogic\0" /* 176 */ + "create\0" /* 199 */ + "PHPStan\\Type\\AcceptsResult\0" /* 206 */ + "toAcceptsResult\0" /* 233 */ + "others\0" /* 249 */ + "and\0" /* 256 */ + "or\0" /* 260 */ + "cb\0" /* 263 */ + "decorateReasons\0" /* 266 */ + "operands\0" /* 282 */ + "extremeIdentity\0" /* 291 */ + "maxMin\0" /* 307 */ + "objects\0" /* 314 */ + "callback\0" /* 322 */ + "lazyMaxMin\0" /* 331 */ + "negate\0" /* 342 */ + "describe"; /* 349 */ inline constexpr reg::PackedArg args[] = { reg::packed(0, 0, 7), /* __construct $result */ reg::packed(28, MAY_BE_ARRAY), /* __construct $reasons */ @@ -81,19 +83,25 @@ inline constexpr reg::PackedArg args[] = { reg::packed(63, 0, 88), /* createMaybe return */ reg::packed(152, MAY_BE_BOOL), /* createFromBoolean $value */ reg::packed(63, 0, 88), /* createFromBoolean return */ - reg::packed(63, 0, 176), /* toAcceptsResult return */ - reg::packed(219, 0, 88, false, true), /* and $others */ + reg::packed(0, 0, 7), /* createFromTrinaryLogic $result */ + reg::packed(63, 0, 88), /* createFromTrinaryLogic return */ + reg::packed(0, 0, 7), /* create $result */ + reg::packed(28, MAY_BE_ARRAY), /* create $reasons */ + reg::packed(36, MAY_BE_ARRAY), /* create $lazyReasons */ + reg::packed(63, 0, 88), /* create return */ + reg::packed(63, 0, 206), /* toAcceptsResult return */ + reg::packed(249, 0, 88, false, true), /* and $others */ reg::packed(63, 0, 88), /* and return */ - reg::packed(219, 0, 88, false, true), /* or $others */ + reg::packed(249, 0, 88, false, true), /* or $others */ reg::packed(63, 0, 88), /* or return */ - reg::packed(233, MAY_BE_CALLABLE), /* decorateReasons $cb */ + reg::packed(263, MAY_BE_CALLABLE), /* decorateReasons $cb */ reg::packed(63, 0, 88), /* decorateReasons return */ - reg::packed(252, 0, 88, false, true), /* extremeIdentity $operands */ + reg::packed(282, 0, 88, false, true), /* extremeIdentity $operands */ reg::packed(63, 0, 88), /* extremeIdentity return */ - reg::packed(252, 0, 88, false, true), /* maxMin $operands */ + reg::packed(282, 0, 88, false, true), /* maxMin $operands */ reg::packed(63, 0, 88), /* maxMin return */ - reg::packed(284, MAY_BE_ARRAY), /* lazyMaxMin $objects */ - reg::packed(292, MAY_BE_CALLABLE), /* lazyMaxMin $callback */ + reg::packed(314, MAY_BE_ARRAY), /* lazyMaxMin $objects */ + reg::packed(322, MAY_BE_CALLABLE), /* lazyMaxMin $callback */ reg::packed(63, 0, 88), /* lazyMaxMin return */ reg::packed(63, 0, 88), /* negate return */ reg::packed(63, MAY_BE_STRING), /* describe return */ @@ -112,15 +120,17 @@ inline constexpr sigtab::Sig createYes = { { 121 /* createYes */, 0, 7, 0, 7, ZE inline constexpr sigtab::Sig createNo = { { 131 /* createNo */, 0, 8, 2, 10, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC } }; inline constexpr sigtab::Sig createMaybe = { { 140 /* createMaybe */, 0, 11, 0, 11, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC } }; inline constexpr sigtab::Sig createFromBoolean = { { 158 /* createFromBoolean */, 1, 12, 1, 13, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC } }; -inline constexpr sigtab::Sig toAcceptsResult = { { 203 /* toAcceptsResult */, 0, 14, 0, 14, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig and_ = { { 226 /* and */, 0, 15, 1, 16, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig or_ = { { 230 /* or */, 0, 17, 1, 18, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig decorateReasons = { { 236 /* decorateReasons */, 1, 19, 1, 20, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig extremeIdentity = { { 261 /* extremeIdentity */, 0, 21, 1, 22, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC } }; -inline constexpr sigtab::Sig maxMin = { { 277 /* maxMin */, 0, 23, 1, 24, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC } }; -inline constexpr sigtab::Sig lazyMaxMin = { { 301 /* lazyMaxMin */, 2, 25, 2, 27, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC } }; -inline constexpr sigtab::Sig negate = { { 312 /* negate */, 0, 28, 0, 28, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig describe = { { 319 /* describe */, 0, 29, 0, 29, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig createFromTrinaryLogic = { { 176 /* createFromTrinaryLogic */, 1, 14, 1, 15, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC } }; +inline constexpr sigtab::Sig create = { { 199 /* create */, 3, 16, 3, 19, ZEND_ACC_PRIVATE | ZEND_ACC_STATIC } }; +inline constexpr sigtab::Sig toAcceptsResult = { { 233 /* toAcceptsResult */, 0, 20, 0, 20, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig and_ = { { 256 /* and */, 0, 21, 1, 22, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig or_ = { { 260 /* or */, 0, 23, 1, 24, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig decorateReasons = { { 266 /* decorateReasons */, 1, 25, 1, 26, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig extremeIdentity = { { 291 /* extremeIdentity */, 0, 27, 1, 28, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC } }; +inline constexpr sigtab::Sig maxMin = { { 307 /* maxMin */, 0, 29, 1, 30, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC } }; +inline constexpr sigtab::Sig lazyMaxMin = { { 331 /* lazyMaxMin */, 2, 31, 2, 33, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC } }; +inline constexpr sigtab::Sig negate = { { 342 /* negate */, 0, 34, 0, 34, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig describe = { { 349 /* describe */, 0, 35, 0, 35, ZEND_ACC_PUBLIC } }; } // namespace sig } // namespace ptdecl::IsSuperTypeOfResult From 518d8e17a21d65d7c8fda86cd71ebd4bbc450071 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 20 Oct 2026 17:33:12 +0200 Subject: [PATCH 09/13] Skip the static-type transforms of types without a StaticType Every method call on a static receiver and every called-on prototype mapped each signature type through a TypeTraverser callback that changes StaticTypes only. Whether a type contains one is now asked once per type object - by the same traversal, answered from the type's native header afterwards - and a type without one is returned as is. -1.18% instructions, -0.71% cycles on the single-process benchmark. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01MMNnG2Zo7wgvSZCzjdk17X --- ...ypeUnresolvedMethodPrototypeReflection.cpp | 5 ++ turbo-ext/src/StaticType.cpp | 49 +++++++++++++++++++ turbo-ext/src/TypeCombinatorCache.cpp | 19 +++++++ turbo-ext/src/TypeTraits.h | 5 ++ turbo-ext/src/support.h | 12 +++++ 5 files changed, 90 insertions(+) diff --git a/turbo-ext/src/CalledOnTypeUnresolvedMethodPrototypeReflection.cpp b/turbo-ext/src/CalledOnTypeUnresolvedMethodPrototypeReflection.cpp index 57c3986c2c1..0a1465aa224 100644 --- a/turbo-ext/src/CalledOnTypeUnresolvedMethodPrototypeReflection.cpp +++ b/turbo-ext/src/CalledOnTypeUnresolvedMethodPrototypeReflection.cpp @@ -147,6 +147,11 @@ class CalledOnTypeUnresolvedMethodPrototypeReflection * closure below over $this); UNDEF = pending exception */ static zv::Val transformStaticType(void *context, zval *type) { + /* the callback changes StaticTypes only: a type without one maps to + * itself */ + bool containsStatic; + if (UNEXPECTED(!pt_type_contains_static(type, containsStatic))) return zv::Val(); + if (!containsStatic) return zv::Val::copyOf(zv::Ref(type)); zval thisZv; ZVAL_OBJ(&thisZv, (zend_object *) context); zv::Val callback = pt_type_native_callback(traverse, &thisZv, NULL); diff --git a/turbo-ext/src/StaticType.cpp b/turbo-ext/src/StaticType.cpp index 541664d0555..a802f57e36b 100644 --- a/turbo-ext/src/StaticType.cpp +++ b/turbo-ext/src/StaticType.cpp @@ -453,6 +453,11 @@ class StaticType * UNDEF = pending exception */ zv::Val transformStaticType(zval *type, zval *scope) const { + /* the callback changes StaticTypes only: a type without one maps to + * itself */ + bool containsStatic; + if (UNEXPECTED(!pt_type_contains_static(type, containsStatic))) return zv::Val(); + if (!containsStatic) return zv::Val::copyOf(zv::Ref(type)); zval selfZv; ZVAL_OBJ(&selfZv, self); zv::Val callback = pt_native_closure(&mapCallbackBody, &selfZv, scope); @@ -767,6 +772,50 @@ static void mapCallbackBody(zval *captures, uint32_t argc, zval *argv, zval *ret *return_value = result.take(); } +/* the TypeTraverser::map() callback of pt_type_contains_static(), capturing + * the flag it raises: a StaticType found is returned as is, and nothing is + * traversed once one was */ +static void containsStaticBody(zval *captures, uint32_t argc, zval *argv, zval *return_value) +{ + bool *found = (bool *) Z_PTR(captures[0]); + zval *type = argc >= 1 ? zv::Ref(&argv[0]).deref().raw() : NULL; + if (UNEXPECTED(type == NULL || argc < 2)) { + zend_throw_error(NULL, "phpstan_turbo: a traversal callback called without a type and its traverse callable"); + return; + } + if (*found || (Z_TYPE_P(type) == IS_OBJECT && instanceof_function(Z_OBJCE_P(type), pt_ce_static_type))) { + *found = true; + ZVAL_COPY(return_value, type); + return; + } + zv::Val traversed = pt_type_call_callable(zv::Ref(&argv[1]).deref().raw(), 1, type); + if (UNEXPECTED(traversed.isUndef())) return; + *return_value = traversed.take(); +} + +bool pt_type_contains_static(zval *type, bool &out) +{ + if (UNEXPECTED(Z_TYPE_P(type) != IS_OBJECT)) { + out = true; + return true; + } + int cached = pt_type_cached_fact(Z_OBJ_P(type), PT_TYPE_FACT_CONTAINS_STATIC); + if (cached >= 0) { + out = cached == 1; + return true; + } + bool found = false; + zval capture; + ZVAL_PTR(&capture, &found); + zv::Val callback = pt_native_closure_new(&containsStaticBody, 1, &capture); + if (UNEXPECTED(callback.isUndef())) return false; + zv::Val mapped = pt_type_traverser_map_of(type, callback.raw()); + if (UNEXPECTED(mapped.isUndef())) return false; + pt_type_cache_fact(Z_OBJ_P(type), PT_TYPE_FACT_CONTAINS_STATIC, found); + out = found; + return true; +} + /* the RecursionGuard::run() thunk `static fn () => $traverse($type)`, * capturing [$type, $traverse] */ static void guardCallbackBody(zval *captures, uint32_t argc, zval *argv, zval *return_value) diff --git a/turbo-ext/src/TypeCombinatorCache.cpp b/turbo-ext/src/TypeCombinatorCache.cpp index e2268bfc7b8..aa347a8de98 100644 --- a/turbo-ext/src/TypeCombinatorCache.cpp +++ b/turbo-ext/src/TypeCombinatorCache.cpp @@ -172,6 +172,8 @@ struct TypeObjectHeader KeyList *memoKeys; uint32_t hashComputed; uint32_t memoGeneration; + /* answers about what the type contains, once asked (PT_TYPE_FACT_*) */ + uint32_t facts; zend_object std; }; @@ -714,6 +716,7 @@ static zend_object *typeObjectCreate(zend_class_entry *ce) header->hashComputed = 0; header->memoKeys = NULL; header->memoGeneration = 0; + header->facts = 0; zend_object_std_init(&header->std, ce); object_properties_init(&header->std, ce); header->std.handlers = pt_type_object_handlers; @@ -747,6 +750,7 @@ static zend_object *typeObjectClone(zend_object *old) header->hashComputed = 0; header->memoKeys = NULL; header->memoGeneration = 0; + header->facts = 0; zend_object_std_init(&header->std, old->ce); header->std.handlers = pt_type_object_handlers; if (PT_CE(old->ce, default_properties_count)) { @@ -994,6 +998,21 @@ zv::Val pt_type_combinator_cache_remove(zval *fromType, zval *typeToRemove) * TypeObjectHeader). Called for every class right after activation declares * it; PHP subclasses inherit create_object from it. A class with an allocator * of its own is left alone and keeps the weak maps. */ +int pt_type_cached_fact(zend_object *type, uint32_t fact) +{ + phpstanturbo::TypeObjectHeader *header = phpstanturbo::typeObjectHeader(type); + if (header == NULL || (header->facts & (fact << 1)) == 0) return -1; + return (header->facts & fact) != 0; +} + +void pt_type_cache_fact(zend_object *type, uint32_t fact, bool holds) +{ + phpstanturbo::TypeObjectHeader *header = phpstanturbo::typeObjectHeader(type); + if (header == NULL) return; + header->facts |= fact << 1; + if (holds) header->facts |= fact; +} + void pt_type_combinator_cache_adopt_class(zend_class_entry *ce, const char *realName) { if (PT_CE(ce, create_object) != NULL) return; diff --git a/turbo-ext/src/TypeTraits.h b/turbo-ext/src/TypeTraits.h index 7320a598db5..f18fc900ab1 100644 --- a/turbo-ext/src/TypeTraits.h +++ b/turbo-ext/src/TypeTraits.h @@ -502,6 +502,11 @@ zv::Val pt_static_type_this_class_name(zend_object *self); * leaves pending propagates. state0/state1 are borrowed, NULL = null. */ typedef void (*pt_native_callback)(zval *state0, zval *state1, uint32_t argc, zval *argv, zval *return_value); zv::Val pt_type_native_callback(pt_native_callback fn, zval *state0, zval *state1); +/* whether TypeTraverser::map() reaches a StaticType (ThisType and + * GenericStaticType included) in the type — the only kind the + * transformStaticType() callbacks change; remembered per type object + * (StaticType.cpp); false = pending exception */ +bool pt_type_contains_static(zval *type, bool &out); /* the holder's state slot (0 or 1), for reading a by-reference `use` back * after the call; borrowed */ zval *pt_type_native_callback_state(zval *callback, int index); diff --git a/turbo-ext/src/support.h b/turbo-ext/src/support.h index 24d4252f56a..6a6c3f8f201 100644 --- a/turbo-ext/src/support.h +++ b/turbo-ext/src/support.h @@ -1151,6 +1151,18 @@ extern zend_class_entry *pt_ce_type_utils; extern zend_class_entry *pt_ce_typehint_helper; /* merged from the parallel port branch */ +/* facts about what a type contains, remembered on the type object (types + * are immutable) — each fact one bit, its "known" bit the next one up + * (TypeCombinatorCache.cpp): pt_type_cached_fact() answers 1 / 0, or -1 + * when not known (or the object carries no header); pt_type_cache_fact() + * records it */ +enum : uint32_t +{ + PT_TYPE_FACT_CONTAINS_STATIC = 1u << 0, +}; +int pt_type_cached_fact(zend_object *type, uint32_t fact); +void pt_type_cache_fact(zend_object *type, uint32_t fact, bool holds); + /* the static combinator (TypeCombinator.cpp); TypeCombinatorCache.cpp calls * its do*() entry points directly */ extern zend_class_entry *pt_ce_type_combinator; From d1976d5a057f294f295a5097aa508cefb8db9f94 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 20 Oct 2026 17:40:05 +0200 Subject: [PATCH 10/13] Pick the return type check's verbosity level only for an error checkReturnType() asked VerbosityLevel::getRecommendedLevelByType() - a traversal of both types - for every return statement, and used the answer only in the messages of the errors it reports. -0.29% instructions on the single-process benchmark. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01MMNnG2Zo7wgvSZCzjdk17X --- src/Rules/FunctionReturnTypeCheck.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Rules/FunctionReturnTypeCheck.php b/src/Rules/FunctionReturnTypeCheck.php index e61965ca3a3..e205930591a 100644 --- a/src/Rules/FunctionReturnTypeCheck.php +++ b/src/Rules/FunctionReturnTypeCheck.php @@ -56,7 +56,6 @@ public function checkReturnType( } $isVoidSuperType = $returnType->isVoid(); - $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($returnType, null); if ($returnValue === null) { if (!$isVoidSuperType->no()) { return []; @@ -65,7 +64,7 @@ public function checkReturnType( return [ RuleErrorBuilder::message(sprintf( $emptyReturnStatementMessage, - $returnType->describe($verbosityLevel), + $returnType->describe(VerbosityLevel::getRecommendedLevelByType($returnType, null)), )) ->line($returnNode->getStartLine()) ->identifier('return.empty') @@ -78,13 +77,12 @@ public function checkReturnType( } $returnValueType = $scope->getType($returnValue); - $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($returnType, $returnValueType); if ($isVoidSuperType->yes()) { return [ RuleErrorBuilder::message(sprintf( $voidMessage, - $returnValueType->describe($verbosityLevel), + $returnValueType->describe(VerbosityLevel::getRecommendedLevelByType($returnType, $returnValueType)), )) ->line($returnNode->getStartLine()) ->identifier('return.void') @@ -94,6 +92,8 @@ public function checkReturnType( $accepts = $this->ruleLevelHelper->accepts($returnType, $returnValueType, $scope->isDeclareStrictTypes()); if (!$accepts->result) { + $verbosityLevel = VerbosityLevel::getRecommendedLevelByType($returnType, $returnValueType); + return [ RuleErrorBuilder::message(sprintf( $typeMismatchMessage, From abb2aa3a0d70ffceba5512a5f83df4b662672b17 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 20 Oct 2026 18:00:17 +0200 Subject: [PATCH 11/13] Skip resolving template types of types without one resolveToBounds() and resolveToDefaults() traverse a type to replace its TemplateTypes and change nothing else. The cached contains-a-StaticType answer becomes a general one - whether a traversal reaches an instance of a class, remembered per type object under its own fact bit - and a type without a TemplateType is returned as is. -0.59% instructions on the single-process benchmark. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01MMNnG2Zo7wgvSZCzjdk17X --- turbo-ext/src/StaticType.cpp | 41 +--------------------- turbo-ext/src/TemplateTypeHelper.cpp | 25 ++++++++++++-- turbo-ext/src/TypeTraits.h | 12 ++++--- turbo-ext/src/TypeTraverser.cpp | 51 ++++++++++++++++++++++++++++ turbo-ext/src/support.h | 1 + 5 files changed, 84 insertions(+), 46 deletions(-) diff --git a/turbo-ext/src/StaticType.cpp b/turbo-ext/src/StaticType.cpp index a802f57e36b..482ae60c51b 100644 --- a/turbo-ext/src/StaticType.cpp +++ b/turbo-ext/src/StaticType.cpp @@ -772,48 +772,9 @@ static void mapCallbackBody(zval *captures, uint32_t argc, zval *argv, zval *ret *return_value = result.take(); } -/* the TypeTraverser::map() callback of pt_type_contains_static(), capturing - * the flag it raises: a StaticType found is returned as is, and nothing is - * traversed once one was */ -static void containsStaticBody(zval *captures, uint32_t argc, zval *argv, zval *return_value) -{ - bool *found = (bool *) Z_PTR(captures[0]); - zval *type = argc >= 1 ? zv::Ref(&argv[0]).deref().raw() : NULL; - if (UNEXPECTED(type == NULL || argc < 2)) { - zend_throw_error(NULL, "phpstan_turbo: a traversal callback called without a type and its traverse callable"); - return; - } - if (*found || (Z_TYPE_P(type) == IS_OBJECT && instanceof_function(Z_OBJCE_P(type), pt_ce_static_type))) { - *found = true; - ZVAL_COPY(return_value, type); - return; - } - zv::Val traversed = pt_type_call_callable(zv::Ref(&argv[1]).deref().raw(), 1, type); - if (UNEXPECTED(traversed.isUndef())) return; - *return_value = traversed.take(); -} - bool pt_type_contains_static(zval *type, bool &out) { - if (UNEXPECTED(Z_TYPE_P(type) != IS_OBJECT)) { - out = true; - return true; - } - int cached = pt_type_cached_fact(Z_OBJ_P(type), PT_TYPE_FACT_CONTAINS_STATIC); - if (cached >= 0) { - out = cached == 1; - return true; - } - bool found = false; - zval capture; - ZVAL_PTR(&capture, &found); - zv::Val callback = pt_native_closure_new(&containsStaticBody, 1, &capture); - if (UNEXPECTED(callback.isUndef())) return false; - zv::Val mapped = pt_type_traverser_map_of(type, callback.raw()); - if (UNEXPECTED(mapped.isUndef())) return false; - pt_type_cache_fact(Z_OBJ_P(type), PT_TYPE_FACT_CONTAINS_STATIC, found); - out = found; - return true; + return pt_type_contains_instance_of(type, pt_ce_static_type, PT_TYPE_FACT_CONTAINS_STATIC, out); } /* the RecursionGuard::run() thunk `static fn () => $traverse($type)`, diff --git a/turbo-ext/src/TemplateTypeHelper.cpp b/turbo-ext/src/TemplateTypeHelper.cpp index 671aec38599..94f40d42b31 100644 --- a/turbo-ext/src/TemplateTypeHelper.cpp +++ b/turbo-ext/src/TemplateTypeHelper.cpp @@ -89,8 +89,21 @@ class TemplateTypeHelper /* resolveToDefaults() / resolveToBounds(): every template type replaced * by its default-or-bound / its bound, repeatedly; UNDEF = pending * exception */ - static zv::Val resolveToDefaults(zval *type) { return mapWith(type, resolveToDefaultsCallback); } - static zv::Val resolveToBounds(zval *type) { return mapMemoizedWith(type, resolveToBoundsCallback); } + static zv::Val resolveToDefaults(zval *type) + { + bool containsTemplate; + if (UNEXPECTED(!containsTemplateType(type, containsTemplate))) return zv::Val(); + if (!containsTemplate) return zv::Val::copyOf(zv::Ref(type)); + return mapWith(type, resolveToDefaultsCallback); + } + + static zv::Val resolveToBounds(zval *type) + { + bool containsTemplate; + if (UNEXPECTED(!containsTemplateType(type, containsTemplate))) return zv::Val(); + if (!containsTemplate) return zv::Val::copyOf(zv::Ref(type)); + return mapMemoizedWith(type, resolveToBoundsCallback); + } /* toArgument(): every template type not owned by a callable inside * $type turned into its argument; UNDEF = pending exception */ @@ -155,6 +168,14 @@ class TemplateTypeHelper } private: + /* the callbacks of resolveToDefaults() / resolveToBounds() change + * TemplateTypes only: a type without one maps to itself; false = + * pending exception */ + [[nodiscard]] static bool containsTemplateType(zval *type, bool &out) + { + return pt_type_contains_instance_of(type, pt_class(PT_CLASS_TEMPLATE_TYPE), PT_TYPE_FACT_CONTAINS_TEMPLATE, out); + } + /* TypeTraverser::map($type, $callback); UNDEF = pending exception */ static zv::Val map(zval *type, zval *callback) { diff --git a/turbo-ext/src/TypeTraits.h b/turbo-ext/src/TypeTraits.h index f18fc900ab1..a33a7efbdd4 100644 --- a/turbo-ext/src/TypeTraits.h +++ b/turbo-ext/src/TypeTraits.h @@ -502,10 +502,14 @@ zv::Val pt_static_type_this_class_name(zend_object *self); * leaves pending propagates. state0/state1 are borrowed, NULL = null. */ typedef void (*pt_native_callback)(zval *state0, zval *state1, uint32_t argc, zval *argv, zval *return_value); zv::Val pt_type_native_callback(pt_native_callback fn, zval *state0, zval *state1); -/* whether TypeTraverser::map() reaches a StaticType (ThisType and - * GenericStaticType included) in the type — the only kind the - * transformStaticType() callbacks change; remembered per type object - * (StaticType.cpp); false = pending exception */ +/* whether TypeTraverser::map() reaches an instance of ce (a class or an + * interface) in the type, remembered on the type object under the fact bit + * (support.h, PT_TYPE_FACT_*) — a traversal whose callback changes only + * such instances maps a type without one to itself (TypeTraverser.cpp); + * false = pending exception */ +bool pt_type_contains_instance_of(zval *type, zend_class_entry *ce, uint32_t fact, bool &out); +/* ... of a StaticType (ThisType and GenericStaticType included) — the only + * kind the transformStaticType() callbacks change (StaticType.cpp) */ bool pt_type_contains_static(zval *type, bool &out); /* the holder's state slot (0 or 1), for reading a by-reference `use` back * after the call; borrowed */ diff --git a/turbo-ext/src/TypeTraverser.cpp b/turbo-ext/src/TypeTraverser.cpp index 74c66ea00dc..85d5b437dfb 100644 --- a/turbo-ext/src/TypeTraverser.cpp +++ b/turbo-ext/src/TypeTraverser.cpp @@ -17,6 +17,7 @@ namespace slots = ptdecl::TypeTraverser::slot; namespace sigs = ptdecl::TypeTraverser::sig; #include "zv.h" #include "TypeTraits.h" +#include "Engine.h" zend_class_entry *pt_ce_type_traverser = NULL; @@ -273,6 +274,56 @@ class TypeTraverser using phpstanturbo::TypeTraverser; +/* {{{ facts about what a type contains */ + +/* the TypeTraverser::map() callback of pt_type_contains_instance_of(), + * capturing [the flag it raises, the class]: an instance found is returned + * as is, and nothing is traversed once one was */ +static void containsInstanceBody(zval *captures, uint32_t argc, zval *argv, zval *return_value) +{ + bool *found = (bool *) Z_PTR(captures[0]); + zend_class_entry *ce = (zend_class_entry *) Z_PTR(captures[1]); + if (UNEXPECTED(argc < 2)) { + zend_throw_error(NULL, "phpstan_turbo: a traversal callback called without a type and its traverse callable"); + return; + } + zval *type = zv::Ref(&argv[0]).deref().raw(); + if (*found || (Z_TYPE_P(type) == IS_OBJECT && instanceof_function(Z_OBJCE_P(type), ce))) { + *found = true; + ZVAL_COPY(return_value, type); + return; + } + zv::Val traversed = pt_type_call_callable(zv::Ref(&argv[1]).deref().raw(), 1, type); + if (UNEXPECTED(traversed.isUndef())) return; + *return_value = traversed.take(); +} + +bool pt_type_contains_instance_of(zval *type, zend_class_entry *ce, uint32_t fact, bool &out) +{ + if (UNEXPECTED(Z_TYPE_P(type) != IS_OBJECT || ce == NULL)) { + out = true; + return true; + } + int cached = pt_type_cached_fact(Z_OBJ_P(type), fact); + if (cached >= 0) { + out = cached == 1; + return true; + } + bool found = false; + zval captures[2]; + ZVAL_PTR(&captures[0], &found); + ZVAL_PTR(&captures[1], ce); + zv::Val callback = pt_native_closure_new(&containsInstanceBody, 2, captures); + if (UNEXPECTED(callback.isUndef())) return false; + zv::Val mapped = TypeTraverser::map(type, callback.raw()); + if (UNEXPECTED(mapped.isUndef())) return false; + pt_type_cache_fact(Z_OBJ_P(type), fact, found); + out = found; + return true; +} + +/* }}} */ + /* {{{ exported helpers */ void pt_type_traverser_rshutdown() diff --git a/turbo-ext/src/support.h b/turbo-ext/src/support.h index 6a6c3f8f201..ad8e48002c5 100644 --- a/turbo-ext/src/support.h +++ b/turbo-ext/src/support.h @@ -1159,6 +1159,7 @@ extern zend_class_entry *pt_ce_typehint_helper; enum : uint32_t { PT_TYPE_FACT_CONTAINS_STATIC = 1u << 0, + PT_TYPE_FACT_CONTAINS_TEMPLATE = 1u << 2, }; int pt_type_cached_fact(zend_object *type, uint32_t fact); void pt_type_cache_fact(zend_object *type, uint32_t fact, bool holds); From af6410d1829b2b0dbd510ec11fd3e74870a50159 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 20 Oct 2026 19:47:36 +0200 Subject: [PATCH 12/13] Keep the scope services in one object the scopes share Every MutatingScope carried the thirteen services, the expression result storage stack and the node callback in a property each - the same values in every scope of a factory, copied into each of the ~900K scopes of a self-analysis subset and released from each again. They now live in a ScopeServices object the factory builds once, and a scope holds one reference to it (37 property slots down to 23). -0.88% instructions, ~-3% cycles on the single-process benchmark. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01MMNnG2Zo7wgvSZCzjdk17X --- src/Analyser/DirectInternalScopeFactory.php | 13 +- src/Analyser/LazyInternalScopeFactory.php | 69 +- src/Analyser/MutatingScope.php | 161 +- src/Analyser/ScopeServices.php | 51 + turbo-ext/src/MutatingScope.cpp | 373 ++- turbo-ext/src/ScopeOps.cpp | 2 +- turbo-ext/src/generated/MutatingScope.h | 2397 +++++++++---------- turbo-ext/src/generated/NodeCallbackScope.h | 12 +- turbo-ext/src/support.h | 4 + turbo-ext/tests/scope-family.php | 38 +- 10 files changed, 1528 insertions(+), 1592 deletions(-) create mode 100644 src/Analyser/ScopeServices.php diff --git a/src/Analyser/DirectInternalScopeFactory.php b/src/Analyser/DirectInternalScopeFactory.php index 602b2ed3718..c0a9007c0c7 100644 --- a/src/Analyser/DirectInternalScopeFactory.php +++ b/src/Analyser/DirectInternalScopeFactory.php @@ -24,6 +24,9 @@ final class DirectInternalScopeFactory implements InternalScopeFactory private ExpressionResultStorageStack $expressionResultStorageStack; + /** The services the created scopes share, built on the first create(). */ + private ?ScopeServices $services = null; + /** * @param callable(Node $node, Scope $scope): void|null $nodeCallback * @param ExtensionsCollection $expressionTypeResolverExtensions @@ -75,9 +78,8 @@ public function create( $className = NodeCallbackScope::class; } - return new $className( + $this->services ??= new ScopeServices( $this->container, - $this, $this->reflectionProvider, $this->initializerExprTypeResolver, $this->expressionTypeResolverExtensions, @@ -87,11 +89,16 @@ public function create( $this->parser, $this->constantResolver, $this->expressionResultStorageStack, - $context, $this->phpVersion, $this->attributeReflectionFactory, $this->configuredPhpVersionRangeHelper, $this->nodeCallback, + ); + + return new $className( + $this->services, + $this, + $context, $declareStrictTypes, $function, $namespace, diff --git a/src/Analyser/LazyInternalScopeFactory.php b/src/Analyser/LazyInternalScopeFactory.php index 297692a2b47..c40ea12abbc 100644 --- a/src/Analyser/LazyInternalScopeFactory.php +++ b/src/Analyser/LazyInternalScopeFactory.php @@ -6,7 +6,6 @@ use PHPStan\Analyser\Generics\TemplateArgumentConstraints; use PHPStan\Analyser\Generics\TemplateArgumentFrame; use PHPStan\DependencyInjection\Container; -use PHPStan\DependencyInjection\ExtensionsCollection; use PHPStan\DependencyInjection\GenerateFactory; use PHPStan\Node\Printer\ExprPrinter; use PHPStan\Parser\Parser; @@ -29,28 +28,10 @@ final class LazyInternalScopeFactory implements InternalScopeFactory private Parser $currentSimpleVersionParser; - private ?ReflectionProvider $reflectionProvider = null; - - private ?InitializerExprTypeResolver $initializerExprTypeResolver = null; - - /** @var ExtensionsCollection|null */ - private ?ExtensionsCollection $expressionTypeResolverExtensions = null; - - private ?ExprPrinter $exprPrinter = null; - - private ?TypeSpecifier $typeSpecifier = null; - - private ?PropertyReflectionFinder $propertyReflectionFinder = null; - - private ?ConstantResolver $constantResolver = null; - private ExpressionResultStorageStack $expressionResultStorageStack; - private ?PhpVersion $phpVersionType = null; - - private ?AttributeReflectionFactory $attributeReflectionFactory = null; - - private ?ConfiguredPhpVersionRangeHelper $configuredPhpVersionRangeHelper = null; + /** The services the created scopes share, built on the first create(). */ + private ?ScopeServices $services = null; private ?self $twin = null; @@ -97,36 +78,27 @@ public function create( $className = NodeCallbackScope::class; } - $this->reflectionProvider ??= $this->container->getByType(ReflectionProvider::class); - $this->initializerExprTypeResolver ??= $this->container->getByType(InitializerExprTypeResolver::class); - $this->expressionTypeResolverExtensions ??= $this->container->getExtensionsCollection(ExpressionTypeResolverExtension::class); - $this->exprPrinter ??= $this->container->getByType(ExprPrinter::class); - $this->typeSpecifier ??= $this->container->getByType(TypeSpecifier::class); - $this->propertyReflectionFinder ??= $this->container->getByType(PropertyReflectionFinder::class); - - $this->constantResolver ??= $this->container->getByType(ConstantResolver::class); - - $this->phpVersionType ??= $this->container->getByType(PhpVersion::class); - $this->attributeReflectionFactory ??= $this->container->getByType(AttributeReflectionFactory::class); - $this->configuredPhpVersionRangeHelper ??= $this->container->getByType(ConfiguredPhpVersionRangeHelper::class); - - return new $className( + $this->services ??= new ScopeServices( $this->container, - $this, - $this->reflectionProvider, - $this->initializerExprTypeResolver, - $this->expressionTypeResolverExtensions, - $this->exprPrinter, - $this->typeSpecifier, - $this->propertyReflectionFinder, + $this->container->getByType(ReflectionProvider::class), + $this->container->getByType(InitializerExprTypeResolver::class), + $this->container->getExtensionsCollection(ExpressionTypeResolverExtension::class), + $this->container->getByType(ExprPrinter::class), + $this->container->getByType(TypeSpecifier::class), + $this->container->getByType(PropertyReflectionFinder::class), $this->currentSimpleVersionParser, - $this->constantResolver, + $this->container->getByType(ConstantResolver::class), $this->expressionResultStorageStack, - $context, - $this->phpVersionType, - $this->attributeReflectionFactory, - $this->configuredPhpVersionRangeHelper, + $this->container->getByType(PhpVersion::class), + $this->container->getByType(AttributeReflectionFactory::class), + $this->container->getByType(ConfiguredPhpVersionRangeHelper::class), $this->nodeCallback, + ); + + return new $className( + $this->services, + $this, + $context, $declareStrictTypes, $function, $namespace, @@ -184,6 +156,9 @@ private function twin(): self $this->twin = new self($this->container, $this->nodeCallback, !$this->createsNodeCallbackScopes, $this->expressionResultStorageStack); $this->twin->origin = WeakReference::create($this); + // the same services for both flavours: the same container, node + // callback and storage stack + $this->twin->services = $this->services; return $this->twin; } diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 2bd8e73b26e..f3e325d7f7d 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -29,8 +29,6 @@ use PHPStan\Analyser\Generics\TemplateArgumentFrame; use PHPStan\Analyser\Traverser\TransformStaticTypeTraverser; use PHPStan\Collectors\Collector; -use PHPStan\DependencyInjection\Container; -use PHPStan\DependencyInjection\ExtensionsCollection; use PHPStan\Node\EmitCollectedDataNode; use PHPStan\Node\Expr\AlwaysRememberedExpr; use PHPStan\Node\Expr\CloneReinitializationExpr; @@ -45,15 +43,11 @@ use PHPStan\Node\IssetExpr; use PHPStan\Node\Printer\ExprPrinter; use PHPStan\Node\VirtualNode; -use PHPStan\Parser\Parser; -use PHPStan\Php\ConfiguredPhpVersionRangeHelper; -use PHPStan\Php\PhpVersion; use PHPStan\Php\PhpVersionFactory; use PHPStan\Php\PhpVersions; use PHPStan\PhpDoc\ResolvedPhpDocBlock; use PHPStan\Reflection\Assertions; use PHPStan\Reflection\AttributeReflection; -use PHPStan\Reflection\AttributeReflectionFactory; use PHPStan\Reflection\ClassConstantReflection; use PHPStan\Reflection\ClassMemberReflection; use PHPStan\Reflection\ClassReflection; @@ -62,15 +56,12 @@ use PHPStan\Reflection\ExtendedPropertyReflection; use PHPStan\Reflection\FunctionReflection; use PHPStan\Reflection\InitializerExprContext; -use PHPStan\Reflection\InitializerExprTypeResolver; use PHPStan\Reflection\MethodReflection; use PHPStan\Reflection\ParameterReflection; use PHPStan\Reflection\ParametersAcceptorSelector; use PHPStan\Reflection\Php\PhpFunctionFromParserNodeReflection; use PHPStan\Reflection\Php\PhpMethodFromParserNodeReflection; use PHPStan\Reflection\PropertyReflection; -use PHPStan\Reflection\ReflectionProvider; -use PHPStan\Rules\Properties\PropertyReflectionFinder; use PHPStan\ShouldNotHappenException; use PHPStan\TrinaryLogic; use PHPStan\Turbo\ShadowedByTurboExtension; @@ -89,7 +80,6 @@ use PHPStan\Type\Constant\ConstantStringType; use PHPStan\Type\ConstantTypeHelper; use PHPStan\Type\ErrorType; -use PHPStan\Type\ExpressionTypeResolverExtension; use PHPStan\Type\GeneralizePrecision; use PHPStan\Type\Generic\TemplateTypeHelper; use PHPStan\Type\Generic\TemplateTypeMap; @@ -189,7 +179,6 @@ class MutatingScope implements Scope, NodeCallbackInvoker, CollectedDataEmitter, private ?self $scopeWithPromotedNativeTypes = null; /** - * @param callable(Node $node, Scope $scope): void|null $nodeCallback * @param array $expressionTypes * @param array $conditionalExpressions * @param list $inClosureBindScopeClasses @@ -197,25 +186,11 @@ class MutatingScope implements Scope, NodeCallbackInvoker, CollectedDataEmitter, * @param array $currentlyAllowedUndefinedExpressions * @param array $nativeExpressionTypes * @param list $inFunctionCallsStack - * @param ExtensionsCollection $expressionTypeResolverExtensions */ public function __construct( - private Container $container, + private ScopeServices $services, protected InternalScopeFactory $scopeFactory, - private ReflectionProvider $reflectionProvider, - private InitializerExprTypeResolver $initializerExprTypeResolver, - private ExtensionsCollection $expressionTypeResolverExtensions, - private ExprPrinter $exprPrinter, - private TypeSpecifier $typeSpecifier, - private PropertyReflectionFinder $propertyReflectionFinder, - private Parser $parser, - private ConstantResolver $constantResolver, - private ExpressionResultStorageStack $expressionResultStorageStack, protected ScopeContext $context, - private PhpVersion $phpVersion, - private AttributeReflectionFactory $attributeReflectionFactory, - private ConfiguredPhpVersionRangeHelper $configuredPhpVersionRangeHelper, - private $nodeCallback = null, private bool $declareStrictTypes = false, private PhpFunctionFromParserNodeReflection|null $function = null, ?string $namespace = null, @@ -429,7 +404,7 @@ public function rememberConstructorScope(): self /** @internal called by ScopeOps */ public function isReadonlyPropertyFetch(PropertyFetch $expr, bool $allowOnlyOnThis): bool { - if (!$this->phpVersion->supportsReadOnlyProperties()) { + if (!$this->services->phpVersion->supportsReadOnlyProperties()) { return false; } @@ -449,7 +424,7 @@ public function isReadonlyPropertyFetch(PropertyFetch $expr, bool $allowOnlyOnTh return false; } - $propertyReflection = $this->propertyReflectionFinder->findPropertyReflectionFromNode($expr, $this); + $propertyReflection = $this->services->propertyReflectionFinder->findPropertyReflectionFromNode($expr, $this); if ($propertyReflection === null) { return false; } @@ -997,12 +972,12 @@ public function hasConstant(Name $name): bool return true; } - return $this->reflectionProvider->hasConstant($name, $this); + return $this->services->reflectionProvider->hasConstant($name, $this); } private function fileHasCompilerHaltStatementCalls(): bool { - $nodes = $this->parser->parseFile($this->getFile()); + $nodes = $this->services->parser->parseFile($this->getFile()); foreach ($nodes as $node) { if ($node instanceof Node\Stmt\HaltCompiler) { return true; @@ -1108,13 +1083,13 @@ public function getScopeNativeType(Expr $expr): Type public function getNodeKey(Expr $node): string { - return ScopeOps::nodeKey($node, $this->exprPrinter); + return ScopeOps::nodeKey($node, $this->services->exprPrinter); } /** @internal */ public function getExprPrinter(): ExprPrinter { - return $this->exprPrinter; + return $this->services->exprPrinter; } /** @@ -1220,7 +1195,7 @@ private static function exprStringIsRootedIn(string $exprString, array $roots): private function resolveType(string $exprString, Expr $node): Type { - foreach ($this->expressionTypeResolverExtensions->getAll() as $extension) { + foreach ($this->services->expressionTypeResolverExtensions->getAll() as $extension) { $type = $extension->getType($node, $this); if ($type !== null) { return $type; @@ -1240,7 +1215,7 @@ private function resolveType(string $exprString, Expr $node): Type return $this->resolveTypeOfNewWorldHandlerNode($node); } - $exprHandler = ExprHandlerRegistry::resolve($node, $this->container); + $exprHandler = ExprHandlerRegistry::resolve($node, $this->services->container); if ($exprHandler !== null) { return $this->resolveTypeOfNewWorldHandlerNode($node); } @@ -1263,7 +1238,7 @@ private function resolveTypeOfNewWorldHandlerNode(Expr $node): Type // engine - a rule's NodeCallbackScope must not flow into result // callbacks or on-demand processing $scope = $this->toWalkScope(); - $storage = $this->expressionResultStorageStack->getCurrent(); + $storage = $this->services->expressionResultStorageStack->getCurrent(); $counterfactualAsk = false; if ($storage !== null) { $result = $storage->findExpressionResult($node); @@ -1288,7 +1263,7 @@ private function resolveTypeOfNewWorldHandlerNode(Expr $node): Type // whose result NodeScopeResolver stores without an eager type. // getClosureType()'s own depth guard answers the self-by-ref ask. if ($node instanceof Expr\Closure || $node instanceof Expr\ArrowFunction) { - return $this->container->getByType(ClosureTypeResolver::class)->getClosureType($scope, $node, false, $storage); + return $this->services->container->getByType(ClosureTypeResolver::class)->getClosureType($scope, $node, false, $storage); } if (!$counterfactualAsk && $storage !== null && $storage->findExpressionResult($node) !== null) { @@ -1299,7 +1274,7 @@ private function resolveTypeOfNewWorldHandlerNode(Expr $node): Type } // a synthetic node, or no analysis in progress - $onDemandResult = $this->container->getByType(NodeScopeResolver::class)->processExprOnDemand( + $onDemandResult = $this->services->container->getByType(NodeScopeResolver::class)->processExprOnDemand( $node, $scope, $storage !== null ? $storage->duplicate() : new ExpressionResultStorage(), @@ -1324,7 +1299,7 @@ private function resolveTypeOfNewWorldHandlerNode(Expr $node): Type */ private function getCurrentTypesOfSpecifiedExpr(Expr $expr): ?array { - $storage = $this->expressionResultStorageStack->getCurrent(); + $storage = $this->services->expressionResultStorageStack->getCurrent(); if ($storage === null) { return null; } @@ -1365,7 +1340,7 @@ private function getCurrentTypesOfSpecifiedExpr(Expr $expr): ?array // showed repeat asks for the same unstored subject on one scope // never happen (0 hits across corpora) $scope = $this->toWalkScope(); - $result = $this->container->getByType(NodeScopeResolver::class)->processExprOnDemand( + $result = $this->services->container->getByType(NodeScopeResolver::class)->processExprOnDemand( $expr, $scope, $storage->duplicate(), @@ -1410,7 +1385,7 @@ public function specifyTypesOfNewWorldHandlerNode(Expr $node, TypeSpecifierConte */ public function obtainResultForNode(Expr $node): ExpressionResult { - $storage = $this->expressionResultStorageStack->getCurrent(); + $storage = $this->services->expressionResultStorageStack->getCurrent(); if ($storage !== null) { $result = $storage->findExpressionResult($node); if ($result !== null) { @@ -1436,7 +1411,7 @@ public function obtainResultForNode(Expr $node): ExpressionResult $scope = $this->toWalkScope(); // a synthetic node, or no analysis in progress - return $this->container->getByType(NodeScopeResolver::class)->processExprOnDemand( + return $this->services->container->getByType(NodeScopeResolver::class)->processExprOnDemand( $node, $scope, $storage !== null ? $storage->duplicate() : new ExpressionResultStorage(), @@ -1450,12 +1425,12 @@ public function obtainResultForNode(Expr $node): ExpressionResult */ public function pushExpressionResultStorage(ExpressionResultStorage $storage): void { - $this->expressionResultStorageStack->push($storage); + $this->services->expressionResultStorageStack->push($storage); } public function popExpressionResultStorage(): void { - $this->expressionResultStorageStack->pop(); + $this->services->expressionResultStorageStack->pop(); } /** @@ -1472,7 +1447,7 @@ public function popExpressionResultStorage(): void /** The settled stored result of the current storage - NodeCallbackScope's no-switch fast path. */ protected function findSettledStoredResult(Expr $node): ?ExpressionResult { - $storage = $this->expressionResultStorageStack->getCurrent(); + $storage = $this->services->expressionResultStorageStack->getCurrent(); if ($storage === null) { return null; } @@ -1482,7 +1457,7 @@ protected function findSettledStoredResult(Expr $node): ?ExpressionResult public function getCurrentExpressionResultStorage(): ?ExpressionResultStorage { - return $this->expressionResultStorageStack->getCurrent(); + return $this->services->expressionResultStorageStack->getCurrent(); } public function withTemplateArgumentFrame(?TemplateArgumentFrame $frame): self @@ -1726,10 +1701,10 @@ public function getKeepVoidType(Expr $node): Type // read directly; a node evaluated on a different scope - e.g. an arrow // body typed on the closure scope - is processed on demand there, its // raw own type keeping void without any keep-void marker on the node. - $storage = $this->expressionResultStorageStack->getCurrent(); + $storage = $this->services->expressionResultStorageStack->getCurrent(); $result = $storage !== null ? $storage->findExpressionResult($node) : null; if ($result === null) { - $result = $this->container->getByType(NodeScopeResolver::class)->processExprOnDemand( + $result = $this->services->container->getByType(NodeScopeResolver::class)->processExprOnDemand( $node, $this->toWalkScope(), $storage !== null ? $storage->duplicate() : new ExpressionResultStorage(), @@ -1806,8 +1781,8 @@ public function resolveTypeByName(Name $name): TypeWithClassName { if ($name->toLowerString() === 'static' && $this->isInClass()) { if ($this->inClosureBindScopeClasses !== [] && $this->inClosureBindScopeClasses !== ['static']) { - if ($this->reflectionProvider->hasClass($this->inClosureBindScopeClasses[0])) { - return new StaticType($this->reflectionProvider->getClass($this->inClosureBindScopeClasses[0])); + if ($this->services->reflectionProvider->hasClass($this->inClosureBindScopeClasses[0])) { + return new StaticType($this->services->reflectionProvider->getClass($this->inClosureBindScopeClasses[0])); } } @@ -1817,8 +1792,8 @@ public function resolveTypeByName(Name $name): TypeWithClassName $originalClass = $this->resolveName($name); if ($this->isInClass()) { if ($this->inClosureBindScopeClasses === [$originalClass]) { - if ($this->reflectionProvider->hasClass($originalClass)) { - return new ThisType($this->reflectionProvider->getClass($originalClass)); + if ($this->services->reflectionProvider->hasClass($originalClass)) { + return new ThisType($this->services->reflectionProvider->getClass($originalClass)); } return new ObjectType($originalClass); } @@ -1845,7 +1820,7 @@ public function getTypeFromValue($value): Type /** @api */ public function hasExpressionType(Expr $node): TrinaryLogic { - return ScopeOps::hasExpressionType($this, $node, $this->exprPrinter); + return ScopeOps::hasExpressionType($this, $node, $this->services->exprPrinter); } /** @@ -2098,7 +2073,7 @@ public function enterClassMethod( $immediatelyInvokedCallableParameters, array_map(fn (Type $type): Type => $this->transformStaticType(TemplateTypeHelper::toArgument($type)), $phpDocClosureThisTypeParameters), $isConstructor, - $this->attributeReflectionFactory->fromAttrGroups($classMethod->attrGroups, InitializerExprContext::fromStubParameter($this->getClassReflection()->getName(), $this->getFile(), $classMethod)), + $this->services->attributeReflectionFactory->fromAttrGroups($classMethod->attrGroups, InitializerExprContext::fromStubParameter($this->getClassReflection()->getName(), $this->getFile(), $classMethod)), $phpDocPureUnlessCallableIsImpureParameters, $phpDocPureUnlessParameterPassedParameters, ), @@ -2190,7 +2165,7 @@ public function enterPropertyHook( [], [], false, - $this->attributeReflectionFactory->fromAttrGroups($hook->attrGroups, InitializerExprContext::fromStubParameter($this->getClassReflection()->getName(), $this->getFile(), $hook)), + $this->services->attributeReflectionFactory->fromAttrGroups($hook->attrGroups, InitializerExprContext::fromStubParameter($this->getClassReflection()->getName(), $this->getFile(), $hook)), [], [], ), @@ -2236,7 +2211,7 @@ private function getRealParameterDefaultValues(Node\FunctionLike $functionLike): if (!$parameter->var instanceof Variable || !is_string($parameter->var->name)) { throw new ShouldNotHappenException(); } - $realParameterDefaultValues[$parameter->var->name] = $this->initializerExprTypeResolver->getType($parameter->default, InitializerExprContext::fromScope($this)); + $realParameterDefaultValues[$parameter->var->name] = $this->services->initializerExprTypeResolver->getType($parameter->default, InitializerExprContext::fromScope($this)); } return $realParameterDefaultValues; @@ -2257,7 +2232,7 @@ private function getParameterAttributes(ClassMethod|Function_|PropertyHook $func throw new ShouldNotHappenException(); } - $parameterAttributes[$parameter->var->name] = $this->attributeReflectionFactory->fromAttrGroups($parameter->attrGroups, InitializerExprContext::fromStubParameter($className, $this->getFile(), $functionLike)); + $parameterAttributes[$parameter->var->name] = $this->services->attributeReflectionFactory->fromAttrGroups($parameter->attrGroups, InitializerExprContext::fromStubParameter($className, $this->getFile(), $functionLike)); } return $parameterAttributes; @@ -2314,7 +2289,7 @@ public function enterFunction( array_map(static fn (Type $type): Type => TemplateTypeHelper::toArgument($type), $parameterOutTypes), $immediatelyInvokedCallableParameters, $phpDocClosureThisTypeParameters, - $this->attributeReflectionFactory->fromAttrGroups($function->attrGroups, InitializerExprContext::fromStubParameter(null, $this->getFile(), $function)), + $this->services->attributeReflectionFactory->fromAttrGroups($function->attrGroups, InitializerExprContext::fromStubParameter(null, $this->getFile(), $function)), $pureUnlessCallableIsImpureParameters, $pureUnlessParameterPassedParameters, ), @@ -2603,7 +2578,7 @@ public function enterAnonymousFunction( ?array $nativeCallableParameters = null, ): self { - $anonymousFunctionReflection = $this->container->getByType(ClosureTypeResolver::class)->getClosureType($this, $closure, true, $this->getCurrentExpressionResultStorage()); + $anonymousFunctionReflection = $this->services->container->getByType(ClosureTypeResolver::class)->getClosureType($this, $closure, true, $this->getCurrentExpressionResultStorage()); $scope = $this->enterAnonymousFunctionWithoutReflection($closure, $callableParameters, $nativeCallableParameters); @@ -2718,7 +2693,7 @@ public function enterAnonymousFunctionWithoutReflection( $expressionTypes['$this'] = ExpressionTypeHolder::createYes($node, $this->getType($node)); $nativeTypes['$this'] = ExpressionTypeHolder::createYes($node, $this->getNativeType($node)); - if ($this->phpVersion->supportsReadOnlyProperties()) { + if ($this->services->phpVersion->supportsReadOnlyProperties()) { foreach ($nonStaticExpressions as $exprString => $typeHolder) { $expr = $typeHolder->getExpr(); @@ -2830,7 +2805,7 @@ private function invalidateStaticExpressions(array $expressionTypes): array */ public function enterArrowFunction(Expr\ArrowFunction $arrowFunction, ?array $callableParameters, ?array $nativeCallableParameters = null): self { - $anonymousFunctionReflection = $this->container->getByType(ClosureTypeResolver::class)->getClosureType($this, $arrowFunction, true, $this->getCurrentExpressionResultStorage()); + $anonymousFunctionReflection = $this->services->container->getByType(ClosureTypeResolver::class)->getClosureType($this, $arrowFunction, true, $this->getCurrentExpressionResultStorage()); $scope = $this->enterArrowFunctionWithoutReflection($arrowFunction, $callableParameters, $nativeCallableParameters); @@ -2940,19 +2915,19 @@ public function getFunctionType($type, bool $isNullable, bool $isVariadic): Type && $this->inClosureBindScopeClasses !== [] && $this->inClosureBindScopeClasses !== ['static'] && in_array($type->toLowerString(), ['static', 'self', 'parent'], true) - && $this->reflectionProvider->hasClass($this->inClosureBindScopeClasses[0]) + && $this->services->reflectionProvider->hasClass($this->inClosureBindScopeClasses[0]) ) { - return $this->initializerExprTypeResolver->getFunctionType( + return $this->services->initializerExprTypeResolver->getFunctionType( $type, $isNullable, false, InitializerExprContext::fromClassReflection( - $this->reflectionProvider->getClass($this->inClosureBindScopeClasses[0]), + $this->services->reflectionProvider->getClass($this->inClosureBindScopeClasses[0]), ), ); } - return $this->initializerExprTypeResolver->getFunctionType($type, $isNullable, false, InitializerExprContext::fromScope($this)); + return $this->services->initializerExprTypeResolver->getFunctionType($type, $isNullable, false, InitializerExprContext::fromScope($this)); } /** @@ -3663,7 +3638,7 @@ private function resolveScopeStateType(Expr $expr, bool $native): Type && !$expr->isFirstClassCallable() && $expr->getArgs() === [] ) { - $storage = $this->expressionResultStorageStack->getCurrent(); + $storage = $this->services->expressionResultStorageStack->getCurrent(); if ($storage !== null && $storage->findExpressionResult($expr) !== null) { return $native ? $this->getNativeType($expr) : $this->getType($expr); } @@ -3693,7 +3668,7 @@ private function resolveScopeStateType(Expr $expr, bool $native): Type || ($expr instanceof Expr\ClassConstFetch && $expr->class instanceof Name && $expr->name instanceof Identifier) || $expr instanceof ConstFetch ) { - return $this->initializerExprTypeResolver->getType($expr, InitializerExprContext::fromScope($this)); + return $this->services->initializerExprTypeResolver->getType($expr, InitializerExprContext::fromScope($this)); } // genuinely non-narrowed expressions (calls, ...) have no @@ -3752,7 +3727,7 @@ private function isSpecifyExpressionTypeNoop(Expr $expr, Type $type): bool } if ($expr instanceof FuncCall && $expr->name instanceof Name && $type->isFalse()->yes()) { - $functionName = $this->reflectionProvider->resolveFunctionName($expr->name, $this); + $functionName = $this->services->reflectionProvider->resolveFunctionName($expr->name, $this); if ($functionName !== null && in_array(strtolower($functionName), [ 'is_dir', 'is_file', @@ -3876,7 +3851,7 @@ public function assignInitializedProperty(Type $fetchedOnType, string $propertyN if ( $function instanceof MethodReflection && strtolower($function->getName()) === '__clone' - && $scope->phpVersion->supportsReadonlyPropertyReinitializationOnClone() + && $scope->services->phpVersion->supportsReadonlyPropertyReinitializationOnClone() ) { $scope = $scope->assignExpression(new CloneReinitializationExpr($propertyName), new MixedType(), new MixedType()); } @@ -3895,7 +3870,7 @@ public function invalidateExpression(Expr $expressionToInvalidate, bool $require $result = ScopeOps::invalidateExpressionEntries( $this, - $this->exprPrinter, + $this->services->exprPrinter, $exprStringToInvalidate, $expressionToInvalidate, $requireMoreCharacters, @@ -3927,7 +3902,7 @@ public function invalidateExpression(Expr $expressionToInvalidate, bool $require public function isPrivatePropertyOfDifferentClass(Expr $expr, ClassReflection $invalidatingClass): bool { if ($expr instanceof Expr\StaticPropertyFetch || $expr instanceof PropertyFetch) { - $propertyReflection = $this->propertyReflectionFinder->findPropertyReflectionFromNode($expr, $this); + $propertyReflection = $this->services->propertyReflectionFinder->findPropertyReflectionFromNode($expr, $this); if ($propertyReflection === null) { return false; } @@ -3943,7 +3918,7 @@ public function isPrivatePropertyOfDifferentClass(Expr $expr, ClassReflection $i private function invalidateMethodsOnExpression(Expr $expressionToInvalidate): self { $result = ScopeOps::invalidateMethodsOnExpression( - $this->exprPrinter, + $this->services->exprPrinter, $this->getNodeKey($expressionToInvalidate), $this->expressionTypes, $this->nativeExpressionTypes, @@ -4071,10 +4046,10 @@ public function removeTypeFromExpression(Expr $expr, Type $typeToRemove): self */ public function filterByTruthyValue(Expr $expr): self { - $specifiedTypes = $this->typeSpecifier->specifyTypesInCondition($this, $expr, TypeSpecifierContext::createTruthy()); + $specifiedTypes = $this->services->typeSpecifier->specifyTypesInCondition($this, $expr, TypeSpecifierContext::createTruthy()); if ($specifiedTypes->isEquality() && $this->getType($expr)->isBoolean()->yes()) { $specifiedTypes = $specifiedTypes->unionWith( - $this->typeSpecifier->create($expr, new ConstantBooleanType(true), TypeSpecifierContext::createTrue(), $this), + $this->services->typeSpecifier->create($expr, new ConstantBooleanType(true), TypeSpecifierContext::createTrue(), $this), ); } @@ -4086,10 +4061,10 @@ public function filterByTruthyValue(Expr $expr): self */ public function filterByFalseyValue(Expr $expr): self { - $specifiedTypes = $this->typeSpecifier->specifyTypesInCondition($this, $expr, TypeSpecifierContext::createFalsey()); + $specifiedTypes = $this->services->typeSpecifier->specifyTypesInCondition($this, $expr, TypeSpecifierContext::createFalsey()); if ($specifiedTypes->isEquality() && $this->getType($expr)->isBoolean()->yes()) { $specifiedTypes = $specifiedTypes->unionWith( - $this->typeSpecifier->create($expr, new ConstantBooleanType(false), TypeSpecifierContext::createTrue(), $this), + $this->services->typeSpecifier->create($expr, new ConstantBooleanType(false), TypeSpecifierContext::createTrue(), $this), ); } @@ -4622,7 +4597,7 @@ private function withoutPreciseClassConstantFetches( continue; } - if ($this->constantResolver->isDynamicClassConstant($this->resolveName($expr->class), $expr->name->toString())) { + if ($this->services->constantResolver->isDynamicClassConstant($this->resolveName($expr->class), $expr->name->toString())) { continue; } @@ -5092,7 +5067,7 @@ private function generalizeVariableTypeHolders( $newVariableTypeHolders = []; foreach ($variableTypeHolders as $variableExprString => $variableTypeHolder) { foreach ($generalizedExpressions as $generalizedExprString => $generalizedExpr) { - if (!ScopeOps::shouldInvalidateExpression($this, $this->exprPrinter, $generalizedExprString, $generalizedExpr, $variableTypeHolder->getExpr(), $variableExprString)) { + if (!ScopeOps::shouldInvalidateExpression($this, $this->services->exprPrinter, $generalizedExprString, $generalizedExpr, $variableTypeHolder->getExpr(), $variableExprString)) { continue; } @@ -5253,7 +5228,7 @@ private function generalizeType(Type $a, Type $b, int $depth): Type $constantArraysB = TypeCombinator::union(...$constantArrays['b']); if ( $constantArraysA->getIterableKeyType()->equals($constantArraysB->getIterableKeyType()) - && $constantArraysA->getArraySize()->getGreaterOrEqualType($this->phpVersion)->isSuperTypeOf($constantArraysB->getArraySize())->yes() + && $constantArraysA->getArraySize()->getGreaterOrEqualType($this->services->phpVersion)->isSuperTypeOf($constantArraysB->getArraySize())->yes() ) { $resultArrayBuilder = ConstantArrayTypeBuilder::createEmpty(); foreach (TypeUtils::flattenTypes($constantArraysA->getIterableKeyType()) as $keyType) { @@ -5310,7 +5285,7 @@ private function generalizeType(Type $a, Type $b, int $depth): Type if ( $constantArraysA->isIterableAtLeastOnce()->yes() && $constantArraysB->isIterableAtLeastOnce()->yes() - && $constantArraysA->getArraySize()->getGreaterOrEqualType($this->phpVersion)->isSuperTypeOf($constantArraysB->getArraySize())->yes() + && $constantArraysA->getArraySize()->getGreaterOrEqualType($this->services->phpVersion)->isSuperTypeOf($constantArraysB->getArraySize())->yes() ) { $accessories[] = new NonEmptyArrayType(); } @@ -5659,7 +5634,7 @@ public function canWriteProperty(ExtendedPropertyReflection $propertyReflection) return $this->canAccessClassMember($propertyReflection); } - if (!$this->phpVersion->supportsAsymmetricVisibility()) { + if (!$this->services->phpVersion->supportsAsymmetricVisibility()) { return $this->canAccessClassMember($propertyReflection); } @@ -5682,11 +5657,11 @@ public function canWriteProperty(ExtendedPropertyReflection $propertyReflection) }; foreach ($this->inClosureBindScopeClasses as $inClosureBindScopeClass) { - if (!$this->reflectionProvider->hasClass($inClosureBindScopeClass)) { + if (!$this->services->reflectionProvider->hasClass($inClosureBindScopeClass)) { continue; } - if ($canAccessClassMember($this->reflectionProvider->getClass($inClosureBindScopeClass))) { + if ($canAccessClassMember($this->services->reflectionProvider->getClass($inClosureBindScopeClass))) { return true; } } @@ -5739,11 +5714,11 @@ private function canAccessClassMember(ClassMemberReflection $classMemberReflecti }; foreach ($this->inClosureBindScopeClasses as $inClosureBindScopeClass) { - if (!$this->reflectionProvider->hasClass($inClosureBindScopeClass)) { + if (!$this->services->reflectionProvider->hasClass($inClosureBindScopeClass)) { continue; } - if ($canAccessClassMember($this->reflectionProvider->getClass($inClosureBindScopeClass))) { + if ($canAccessClassMember($this->services->reflectionProvider->getClass($inClosureBindScopeClass))) { return true; } } @@ -5901,7 +5876,7 @@ public function getConstantReflection(Type $typeWithConstant, string $constantNa public function getConstantExplicitTypeFromConfig(string $constantName, Type $constantType): Type { - return $this->constantResolver->resolveConstantType($constantName, $constantType); + return $this->services->constantResolver->resolveConstantType($constantName, $constantType); } /** @@ -6028,7 +6003,7 @@ public function getPhpVersion(): PhpVersions // config or from the composer.json "require.php" constraint - the very same // source ConstantResolver narrows PHP_VERSION_ID with, so that // Scope::getPhpVersion() never contradicts the PHP_VERSION_ID constant. - [$minPhpVersion, $maxPhpVersion] = $this->configuredPhpVersionRangeHelper->getVersionRange(); + [$minPhpVersion, $maxPhpVersion] = $this->services->configuredPhpVersionRangeHelper->getVersionRange(); if ( $minPhpVersion !== null || ($maxPhpVersion !== null && $maxPhpVersion->getVersionId() !== PhpVersionFactory::MAX_PHP_VERSION) @@ -6039,7 +6014,7 @@ public function getPhpVersion(): PhpVersions )); } - return new PhpVersions(new ConstantIntegerType($this->phpVersion->getVersionId())); + return new PhpVersions(new ConstantIntegerType($this->services->phpVersion->getVersionId())); } /** @@ -6055,7 +6030,7 @@ private function isOverallPhpVersionRange(Type $type): bool public function invokeNodeCallback(Node $node): void { - $nodeCallback = $this->nodeCallback; + $nodeCallback = $this->services->nodeCallback; if ($nodeCallback === null) { throw new ShouldNotHappenException('Node callback is not present in this scope'); } @@ -6071,7 +6046,7 @@ public function invokeNodeCallback(Node $node): void */ public function emitCollectedData(string $collectorType, mixed $data): void { - $nodeCallback = $this->nodeCallback; + $nodeCallback = $this->services->nodeCallback; if ($nodeCallback === null) { throw new ShouldNotHappenException('Node callback is not present in this scope'); } @@ -6082,22 +6057,22 @@ public function emitCollectedData(string $collectorType, mixed $data): void public function trackValueDependency(string $extensionClass, string $key): void { // a scope without a node callback is outside the walk of the analysed file - see ValueDependencyCollector - $this->container->getByType(ValueDependencyCollector::class)->record($extensionClass, $key, $this, $this->nodeCallback !== null); + $this->services->container->getByType(ValueDependencyCollector::class)->record($extensionClass, $key, $this, $this->services->nodeCallback !== null); } public function trackFileDependency(string $file): void { - $this->container->getByType(ValueDependencyCollector::class)->recordFile($file, $this, $this->nodeCallback !== null); + $this->services->container->getByType(ValueDependencyCollector::class)->recordFile($file, $this, $this->services->nodeCallback !== null); } public function trackDirectoryDependency(string $directory, string $pattern = '*'): void { - $this->container->getByType(ValueDependencyCollector::class)->recordDirectory($directory, $pattern, $this, $this->nodeCallback !== null); + $this->services->container->getByType(ValueDependencyCollector::class)->recordDirectory($directory, $pattern, $this, $this->services->nodeCallback !== null); } public function trackClassDependency(string $className): void { - $this->container->getByType(ValueDependencyCollector::class)->recordClass($className, $this, $this->nodeCallback !== null); + $this->services->container->getByType(ValueDependencyCollector::class)->recordClass($className, $this, $this->services->nodeCallback !== null); } } diff --git a/src/Analyser/ScopeServices.php b/src/Analyser/ScopeServices.php new file mode 100644 index 00000000000..72bbc767679 --- /dev/null +++ b/src/Analyser/ScopeServices.php @@ -0,0 +1,51 @@ + $expressionTypeResolverExtensions + * @param (callable(Node $node, Scope $scope): void)|null $nodeCallback + */ + public function __construct( + public readonly Container $container, + public readonly ReflectionProvider $reflectionProvider, + public readonly InitializerExprTypeResolver $initializerExprTypeResolver, + public readonly ExtensionsCollection $expressionTypeResolverExtensions, + public readonly ExprPrinter $exprPrinter, + public readonly TypeSpecifier $typeSpecifier, + public readonly PropertyReflectionFinder $propertyReflectionFinder, + public readonly Parser $parser, + public readonly ConstantResolver $constantResolver, + public readonly ExpressionResultStorageStack $expressionResultStorageStack, + public readonly PhpVersion $phpVersion, + public readonly AttributeReflectionFactory $attributeReflectionFactory, + public readonly ConfiguredPhpVersionRangeHelper $configuredPhpVersionRangeHelper, + public readonly mixed $nodeCallback, + ) + { + } + +} diff --git a/turbo-ext/src/MutatingScope.cpp b/turbo-ext/src/MutatingScope.cpp index c4c6424a79b..899d5e30270 100644 --- a/turbo-ext/src/MutatingScope.cpp +++ b/turbo-ext/src/MutatingScope.cpp @@ -300,22 +300,9 @@ enum : uint32_t PT_MS_PROP_NAMESPACE, PT_MS_PROP_SCOPE_OUT_OF_FIRST_LEVEL_STATEMENT, PT_MS_PROP_SCOPE_WITH_PROMOTED_NATIVE_TYPES, - PT_MS_PROP_CONTAINER, + PT_MS_PROP_SERVICES, PT_MS_PROP_SCOPE_FACTORY, - PT_MS_PROP_REFLECTION_PROVIDER, - PT_MS_PROP_INITIALIZER_EXPR_TYPE_RESOLVER, - PT_MS_PROP_EXPRESSION_TYPE_RESOLVER_EXTENSIONS, - PT_MS_PROP_EXPR_PRINTER, - PT_MS_PROP_TYPE_SPECIFIER, - PT_MS_PROP_PROPERTY_REFLECTION_FINDER, - PT_MS_PROP_PARSER, - PT_MS_PROP_CONSTANT_RESOLVER, - PT_MS_PROP_EXPRESSION_RESULT_STORAGE_STACK, PT_MS_PROP_CONTEXT, - PT_MS_PROP_PHP_VERSION, - PT_MS_PROP_ATTRIBUTE_REFLECTION_FACTORY, - PT_MS_PROP_CONFIGURED_PHP_VERSION_RANGE_HELPER, - PT_MS_PROP_NODE_CALLBACK, PT_MS_PROP_DECLARE_STRICT_TYPES, PT_MS_PROP_FUNCTION, PT_MS_PROP_EXPRESSION_TYPES, @@ -335,6 +322,73 @@ enum : uint32_t PT_MS_PROP_COUNT, }; +/* the properties of the ScopeServices object the scope's $services holds + * (ScopeServices.php), in its declaration order */ +enum : uint32_t +{ + PT_MSS_CONTAINER = 0, + PT_MSS_REFLECTION_PROVIDER, + PT_MSS_INITIALIZER_EXPR_TYPE_RESOLVER, + PT_MSS_EXPRESSION_TYPE_RESOLVER_EXTENSIONS, + PT_MSS_EXPR_PRINTER, + PT_MSS_TYPE_SPECIFIER, + PT_MSS_PROPERTY_REFLECTION_FINDER, + PT_MSS_PARSER, + PT_MSS_CONSTANT_RESOLVER, + PT_MSS_EXPRESSION_RESULT_STORAGE_STACK, + PT_MSS_PHP_VERSION, + PT_MSS_ATTRIBUTE_REFLECTION_FACTORY, + PT_MSS_CONFIGURED_PHP_VERSION_RANGE_HELPER, + PT_MSS_NODE_CALLBACK, + PT_MSS_COUNT, +}; + +static const char *const pt_mss_names[PT_MSS_COUNT] = { + "container", + "reflectionProvider", + "initializerExprTypeResolver", + "expressionTypeResolverExtensions", + "exprPrinter", + "typeSpecifier", + "propertyReflectionFinder", + "parser", + "constantResolver", + "expressionResultStorageStack", + "phpVersion", + "attributeReflectionFactory", + "configuredPhpVersionRangeHelper", + "nodeCallback", +}; + +/* $services->: the slot of the ScopeServices object, by offsets + * resolved once per class entry; a static UNDEF while $services is unwritten + * (or not a ScopeServices) */ +static zval pt_mss_undef; + +static zval *pt_ms_service_of(zval *services, uint32_t which) +{ + static zend_class_entry *ce = nullptr; + static int32_t offsets[PT_MSS_COUNT]; + if (UNEXPECTED(Z_TYPE_P(services) != IS_OBJECT)) { + ZVAL_UNDEF(&pt_mss_undef); + return &pt_mss_undef; + } + zend_object *object = Z_OBJ_P(services); + if (UNEXPECTED(object->ce != ce)) { + for (uint32_t i = 0; i < PT_MSS_COUNT; i++) { + offsets[i] = pt_instance_prop_offset(object->ce, pt_mss_names[i], strlen(pt_mss_names[i])); + } + ce = object->ce; + } + if (UNEXPECTED(offsets[which] < 0)) { + ZVAL_UNDEF(&pt_mss_undef); + return &pt_mss_undef; + } + zval *slot = OBJ_PROP(object, (uint32_t) offsets[which]); + ZVAL_DEREF(slot); + return slot; +} + /* private const COMPLEX_UNION_TYPE_MEMBER_LIMIT */ #define PT_MS_COMPLEX_UNION_TYPE_MEMBER_LIMIT 8 @@ -409,46 +463,12 @@ static void ZEND_FASTCALL msFilterTypeWithMethod(INTERNAL_FUNCTION_PARAMETERS); * does, leaving the twin's create() to the first call of each factory (while * the memos are still null) and to any other InternalScopeFactory. */ -/* the services create() passes on, in the scope constructor's parameter - * order; all of them are `??=` memos the first create() fills */ -enum : uint32_t -{ - PT_ISF_REFLECTION_PROVIDER = 0, - PT_ISF_INITIALIZER_EXPR_TYPE_RESOLVER, - PT_ISF_EXPRESSION_TYPE_RESOLVER_EXTENSIONS, - PT_ISF_EXPR_PRINTER, - PT_ISF_TYPE_SPECIFIER, - PT_ISF_PROPERTY_REFLECTION_FINDER, - PT_ISF_CONSTANT_RESOLVER, - PT_ISF_PHP_VERSION, - PT_ISF_ATTRIBUTE_REFLECTION_FACTORY, - PT_ISF_CONFIGURED_PHP_VERSION_RANGE_HELPER, - PT_ISF_MEMO_COUNT -}; - -static const char *const pt_isf_memo_names[PT_ISF_MEMO_COUNT] = { - "reflectionProvider", - "initializerExprTypeResolver", - "expressionTypeResolverExtensions", - "exprPrinter", - "typeSpecifier", - "propertyReflectionFinder", - "constantResolver", - "phpVersionType", - "attributeReflectionFactory", - "configuredPhpVersionRangeHelper", -}; - /* the instance-property slot offsets of the factory's class entry, resolved * once (the twin is final, so there is one) and forgotten at rinit */ struct InternalScopeFactorySlots { zend_class_entry *ce; - uint32_t memos[PT_ISF_MEMO_COUNT]; - uint32_t container; - uint32_t parser; - uint32_t expressionResultStorageStack; - uint32_t nodeCallback; + uint32_t services; uint32_t createsNodeCallbackScopes; uint32_t twin; uint32_t origin; @@ -477,33 +497,21 @@ static const InternalScopeFactorySlots *internalScopeFactorySlots(zend_object *f if (factory->ce != ce) return NULL; InternalScopeFactorySlots slots; slots.ce = ce; - int32_t offsets[PT_ISF_MEMO_COUNT + 7]; - for (uint32_t i = 0; i < PT_ISF_MEMO_COUNT; i++) { - offsets[i] = pt_instance_prop_offset(ce, pt_isf_memo_names[i], strlen(pt_isf_memo_names[i])); - } - offsets[PT_ISF_MEMO_COUNT + 0] = pt_instance_prop_offset(ce, PT_LC("container")); - offsets[PT_ISF_MEMO_COUNT + 1] = pt_instance_prop_offset(ce, PT_LC("currentSimpleVersionParser")); - offsets[PT_ISF_MEMO_COUNT + 2] = pt_instance_prop_offset(ce, PT_LC("expressionResultStorageStack")); - offsets[PT_ISF_MEMO_COUNT + 3] = pt_instance_prop_offset(ce, PT_LC("nodeCallback")); - offsets[PT_ISF_MEMO_COUNT + 4] = pt_instance_prop_offset(ce, PT_LC("createsNodeCallbackScopes")); - offsets[PT_ISF_MEMO_COUNT + 5] = pt_instance_prop_offset(ce, PT_LC("twin")); - offsets[PT_ISF_MEMO_COUNT + 6] = pt_instance_prop_offset(ce, PT_LC("origin")); - for (uint32_t i = 0; i < PT_ISF_MEMO_COUNT + 7; i++) { + int32_t offsets[4]; + offsets[0] = pt_instance_prop_offset(ce, PT_LC("services")); + offsets[1] = pt_instance_prop_offset(ce, PT_LC("createsNodeCallbackScopes")); + offsets[2] = pt_instance_prop_offset(ce, PT_LC("twin")); + offsets[3] = pt_instance_prop_offset(ce, PT_LC("origin")); + for (uint32_t i = 0; i < 4; i++) { if (UNEXPECTED(offsets[i] < 0)) { /* not the twin this reader knows: every call goes through the method */ return NULL; } } - for (uint32_t i = 0; i < PT_ISF_MEMO_COUNT; i++) { - slots.memos[i] = (uint32_t) offsets[i]; - } - slots.container = (uint32_t) offsets[PT_ISF_MEMO_COUNT + 0]; - slots.parser = (uint32_t) offsets[PT_ISF_MEMO_COUNT + 1]; - slots.expressionResultStorageStack = (uint32_t) offsets[PT_ISF_MEMO_COUNT + 2]; - slots.nodeCallback = (uint32_t) offsets[PT_ISF_MEMO_COUNT + 3]; - slots.createsNodeCallbackScopes = (uint32_t) offsets[PT_ISF_MEMO_COUNT + 4]; - slots.twin = (uint32_t) offsets[PT_ISF_MEMO_COUNT + 5]; - slots.origin = (uint32_t) offsets[PT_ISF_MEMO_COUNT + 6]; + slots.services = (uint32_t) offsets[0]; + slots.createsNodeCallbackScopes = (uint32_t) offsets[1]; + slots.twin = (uint32_t) offsets[2]; + slots.origin = (uint32_t) offsets[3]; pt_isf_slots = slots; return &pt_isf_slots; } @@ -627,6 +635,20 @@ class MutatingScope zv::Val copyOfSlot(uint32_t index) const { return zv::Val::copyOf(slot(index)); } + /* $this->services-> (PT_MSS_*) — UNDEF while the constructor has + * not written $services */ + zv::Ref service(uint32_t which) const { return zv::Ref(pt_ms_service_of(slot(PT_MS_PROP_SERVICES).deref().raw(), which)); } + + /* $services written: the twin's Error otherwise */ + bool requireService() + { + if (UNEXPECTED(slot(PT_MS_PROP_SERVICES).isUndef())) { + (void) uninitializedProperty("services"); + return false; + } + return true; + } + bool slotBool(uint32_t index) const { return Z_TYPE_P(slot(index).raw()) == IS_TRUE; } zval *thisZval() @@ -891,17 +913,10 @@ class MutatingScope if (UNEXPECTED(nodeCallbackScope == NULL || pt_ce_mutating_scope == NULL || nodeCallbackScope->parent != pt_ce_mutating_scope)) { return factoryCreateCall(factory, args); } - for (uint32_t i = 0; i < PT_ISF_MEMO_COUNT; i++) { - if (UNEXPECTED(Z_TYPE_P(OBJ_PROP(factory, slots->memos[i])) != IS_OBJECT)) return factoryCreateCall(factory, args); - } - zval *container = OBJ_PROP(factory, slots->container); - zval *parser = OBJ_PROP(factory, slots->parser); - zval *storageStack = OBJ_PROP(factory, slots->expressionResultStorageStack); - if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT || Z_TYPE_P(parser) != IS_OBJECT || Z_TYPE_P(storageStack) != IS_OBJECT)) { - /* an uninitialized promoted property — the twin's Error, raised - * by the method reading it */ - return factoryCreateCall(factory, args); - } + /* $this->services ??= new ScopeServices(...): the method builds it on + * the first create() */ + zval *services = OBJ_PROP(factory, slots->services); + if (UNEXPECTED(Z_TYPE_P(services) != IS_OBJECT)) return factoryCreateCall(factory, args); /* the argument types the twin's create() signature would enforce and * the new scope reads without checking; anything else is the method's @@ -930,22 +945,9 @@ class MutatingScope ConstructArgs a = {}; zval factoryZval; ZVAL_OBJ(&factoryZval, factory); - a.container = container; + a.services = services; a.scopeFactory = &factoryZval; - a.reflectionProvider = OBJ_PROP(factory, slots->memos[PT_ISF_REFLECTION_PROVIDER]); - a.initializerExprTypeResolver = OBJ_PROP(factory, slots->memos[PT_ISF_INITIALIZER_EXPR_TYPE_RESOLVER]); - a.expressionTypeResolverExtensions = OBJ_PROP(factory, slots->memos[PT_ISF_EXPRESSION_TYPE_RESOLVER_EXTENSIONS]); - a.exprPrinter = OBJ_PROP(factory, slots->memos[PT_ISF_EXPR_PRINTER]); - a.typeSpecifier = OBJ_PROP(factory, slots->memos[PT_ISF_TYPE_SPECIFIER]); - a.propertyReflectionFinder = OBJ_PROP(factory, slots->memos[PT_ISF_PROPERTY_REFLECTION_FINDER]); - a.parser = parser; - a.constantResolver = OBJ_PROP(factory, slots->memos[PT_ISF_CONSTANT_RESOLVER]); - a.expressionResultStorageStack = storageStack; a.context = &args.argv[CreateArgs::CONTEXT]; - a.phpVersion = OBJ_PROP(factory, slots->memos[PT_ISF_PHP_VERSION]); - a.attributeReflectionFactory = OBJ_PROP(factory, slots->memos[PT_ISF_ATTRIBUTE_REFLECTION_FACTORY]); - a.configuredPhpVersionRangeHelper = OBJ_PROP(factory, slots->memos[PT_ISF_CONFIGURED_PHP_VERSION_RANGE_HELPER]); - a.nodeCallback = OBJ_PROP(factory, slots->nodeCallback); a.declareStrictTypes = Z_TYPE(args.argv[CreateArgs::DECLARE_STRICT_TYPES]) == IS_TRUE; a.function = &args.argv[CreateArgs::FUNCTION]; a.ns = Z_TYPE(args.argv[CreateArgs::NAMESPACE_]) == IS_STRING ? Z_STR(args.argv[CreateArgs::NAMESPACE_]) : NULL; @@ -1033,11 +1035,11 @@ class MutatingScope /* {{{ __construct */ - /* the 33 constructor arguments as zpp delivers them (NULL = a defaulted + /* the 20 constructor arguments as zpp delivers them (NULL = a defaulted * optional parameter) */ struct ConstructArgs { - zval *container, *scopeFactory, *reflectionProvider, *initializerExprTypeResolver, *expressionTypeResolverExtensions, *exprPrinter, *typeSpecifier, *propertyReflectionFinder, *parser, *constantResolver, *expressionResultStorageStack, *context, *phpVersion, *attributeReflectionFactory, *configuredPhpVersionRangeHelper, *nodeCallback; + zval *services, *scopeFactory, *context; bool declareStrictTypes; zval *function; zend_string *ns; @@ -1052,22 +1054,9 @@ class MutatingScope void construct(const ConstructArgs &a) { - writeSlot(PT_MS_PROP_CONTAINER, zv::Val::copyOf(zv::Ref(a.container))); + writeSlot(PT_MS_PROP_SERVICES, zv::Val::copyOf(zv::Ref(a.services))); writeSlot(PT_MS_PROP_SCOPE_FACTORY, zv::Val::copyOf(zv::Ref(a.scopeFactory))); - writeSlot(PT_MS_PROP_REFLECTION_PROVIDER, zv::Val::copyOf(zv::Ref(a.reflectionProvider))); - writeSlot(PT_MS_PROP_INITIALIZER_EXPR_TYPE_RESOLVER, zv::Val::copyOf(zv::Ref(a.initializerExprTypeResolver))); - writeSlot(PT_MS_PROP_EXPRESSION_TYPE_RESOLVER_EXTENSIONS, zv::Val::copyOf(zv::Ref(a.expressionTypeResolverExtensions))); - writeSlot(PT_MS_PROP_EXPR_PRINTER, zv::Val::copyOf(zv::Ref(a.exprPrinter))); - writeSlot(PT_MS_PROP_TYPE_SPECIFIER, zv::Val::copyOf(zv::Ref(a.typeSpecifier))); - writeSlot(PT_MS_PROP_PROPERTY_REFLECTION_FINDER, zv::Val::copyOf(zv::Ref(a.propertyReflectionFinder))); - writeSlot(PT_MS_PROP_PARSER, zv::Val::copyOf(zv::Ref(a.parser))); - writeSlot(PT_MS_PROP_CONSTANT_RESOLVER, zv::Val::copyOf(zv::Ref(a.constantResolver))); - writeSlot(PT_MS_PROP_EXPRESSION_RESULT_STORAGE_STACK, zv::Val::copyOf(zv::Ref(a.expressionResultStorageStack))); writeSlot(PT_MS_PROP_CONTEXT, zv::Val::copyOf(zv::Ref(a.context))); - writeSlot(PT_MS_PROP_PHP_VERSION, zv::Val::copyOf(zv::Ref(a.phpVersion))); - writeSlot(PT_MS_PROP_ATTRIBUTE_REFLECTION_FACTORY, zv::Val::copyOf(zv::Ref(a.attributeReflectionFactory))); - writeSlot(PT_MS_PROP_CONFIGURED_PHP_VERSION_RANGE_HELPER, zv::Val::copyOf(zv::Ref(a.configuredPhpVersionRangeHelper))); - writeSlot(PT_MS_PROP_NODE_CALLBACK, optional(a.nodeCallback)); writeSlot(PT_MS_PROP_DECLARE_STRICT_TYPES, zv::Val::boolean(a.declareStrictTypes)); writeSlot(PT_MS_PROP_FUNCTION, optional(a.function)); /* if ($namespace === '') { $namespace = null; } $this->namespace = $namespace; */ @@ -1373,7 +1362,7 @@ class MutatingScope /** @internal called by ScopeOps; false = pending exception */ [[nodiscard]] bool isReadonlyPropertyFetch(zend_object *exprObject, bool allowOnlyOnThis, bool &out) { - zv::Ref phpVersion = slot(PT_MS_PROP_PHP_VERSION); + zv::Ref phpVersion = service(PT_MSS_PHP_VERSION); if (UNEXPECTED(!phpVersion.isObject())) { (void) uninitializedProperty("phpVersion"); return false; @@ -1415,7 +1404,7 @@ class MutatingScope return true; } - zv::Ref finder = slot(PT_MS_PROP_PROPERTY_REFLECTION_FINDER); + zv::Ref finder = service(PT_MSS_PROPERTY_REFLECTION_FINDER); if (UNEXPECTED(!finder.isObject())) { (void) uninitializedProperty("propertyReflectionFinder"); return false; @@ -2014,7 +2003,7 @@ class MutatingScope return true; } - zv::Ref reflectionProvider = slot(PT_MS_PROP_REFLECTION_PROVIDER); + zv::Ref reflectionProvider = service(PT_MSS_REFLECTION_PROVIDER); if (UNEXPECTED(!reflectionProvider.isObject())) { (void) uninitializedProperty("reflectionProvider"); return false; @@ -2029,7 +2018,7 @@ class MutatingScope /* private; false = pending exception */ [[nodiscard]] bool fileHasCompilerHaltStatementCalls(bool &out) { - zv::Ref parser = slot(PT_MS_PROP_PARSER); + zv::Ref parser = service(PT_MSS_PARSER); if (UNEXPECTED(!parser.isObject())) { (void) uninitializedProperty("parser"); return false; @@ -2086,7 +2075,7 @@ class MutatingScope * exception, else null or the storage */ zv::Val currentStorage() { - zv::Ref stack = slot(PT_MS_PROP_EXPRESSION_RESULT_STORAGE_STACK); + zv::Ref stack = service(PT_MSS_EXPRESSION_RESULT_STORAGE_STACK); if (UNEXPECTED(!stack.isObject())) return uninitializedProperty("expressionResultStorageStack"); return pt_expression_result_storage_stack_current(stack.raw()); } @@ -2118,7 +2107,7 @@ class MutatingScope /* $this->container->getByType($className); UNDEF = pending exception */ zv::Val containerGetByType(const char *className, size_t len) { - zv::Ref container = slot(PT_MS_PROP_CONTAINER); + zv::Ref container = service(PT_MSS_CONTAINER); if (UNEXPECTED(!container.isObject())) return uninitializedProperty("container"); zval name; ZVAL_STRINGL(&name, className, len); @@ -2698,7 +2687,7 @@ class MutatingScope /* private */ zv::Val resolveType(zend_string *exprString, zend_object *node) { - zv::Ref extensions = slot(PT_MS_PROP_EXPRESSION_TYPE_RESOLVER_EXTENSIONS); + zv::Ref extensions = service(PT_MSS_EXPRESSION_TYPE_RESOLVER_EXTENSIONS); if (UNEXPECTED(!extensions.isObject())) return uninitializedProperty("expressionTypeResolverExtensions"); zv::Val all = pt_extensions_collection_get_all(extensions.asObject()); if (UNEXPECTED(all.isUndef())) return zv::Val(); @@ -2736,7 +2725,7 @@ class MutatingScope if (fcc) return resolveTypeOfNewWorldHandlerNode(node); } - zv::Ref container = slot(PT_MS_PROP_CONTAINER); + zv::Ref container = service(PT_MSS_CONTAINER); if (UNEXPECTED(!container.isObject())) return uninitializedProperty("container"); zv::Val exprHandler = pt_expr_handler_registry_resolve(node, container.raw()); if (UNEXPECTED(exprHandler.isUndef())) return zv::Val(); @@ -2971,7 +2960,7 @@ class MutatingScope /* false = pending exception */ [[nodiscard]] bool pushExpressionResultStorage(zval *storage) { - zv::Ref stack = slot(PT_MS_PROP_EXPRESSION_RESULT_STORAGE_STACK); + zv::Ref stack = service(PT_MSS_EXPRESSION_RESULT_STORAGE_STACK); if (UNEXPECTED(!stack.isObject())) { (void) uninitializedProperty("expressionResultStorageStack"); return false; @@ -2981,7 +2970,7 @@ class MutatingScope bool popExpressionResultStorage() { - zv::Ref stack = slot(PT_MS_PROP_EXPRESSION_RESULT_STORAGE_STACK); + zv::Ref stack = service(PT_MSS_EXPRESSION_RESULT_STORAGE_STACK); if (UNEXPECTED(!stack.isObject())) { (void) uninitializedProperty("expressionResultStorageStack"); return false; @@ -3502,7 +3491,7 @@ class MutatingScope if (UNEXPECTED(EG(exception))) return zv::Val(); first = &nullZv; } - zv::Ref provider = slot(PT_MS_PROP_REFLECTION_PROVIDER); + zv::Ref provider = service(PT_MSS_REFLECTION_PROVIDER); if (UNEXPECTED(!provider.isObject())) return uninitializedProperty("reflectionProvider"); bool hasClass; if (UNEXPECTED(!pt_reflection_provider_has_class(provider.asObject(), first, hasClass))) return zv::Val(); @@ -3533,7 +3522,7 @@ class MutatingScope if (UNEXPECTED(!requireSlot(PT_MS_PROP_IN_CLOSURE_BIND_SCOPE_CLASSES, "inClosureBindScopeClasses"))) return zv::Val(); HashTable *bindScopeClasses = Z_ARRVAL_P(slot(PT_MS_PROP_IN_CLOSURE_BIND_SCOPE_CLASSES).raw()); if (isSingleStringList(bindScopeClasses, ZSTR_VAL(Z_STR_P(originalClass.raw())), ZSTR_LEN(Z_STR_P(originalClass.raw())))) { - zv::Ref provider = slot(PT_MS_PROP_REFLECTION_PROVIDER); + zv::Ref provider = service(PT_MSS_REFLECTION_PROVIDER); if (UNEXPECTED(!provider.isObject())) return uninitializedProperty("reflectionProvider"); bool hasClass; if (UNEXPECTED(!pt_reflection_provider_has_class(provider.asObject(), originalClass.raw(), hasClass))) return zv::Val(); @@ -3927,8 +3916,8 @@ class MutatingScope // config or from the composer.json "require.php" constraint - the very same // source ConstantResolver narrows PHP_VERSION_ID with, so that // Scope::getPhpVersion() never contradicts the PHP_VERSION_ID constant. - if (UNEXPECTED(!requireSlot(PT_MS_PROP_CONFIGURED_PHP_VERSION_RANGE_HELPER, "configuredPhpVersionRangeHelper"))) return zv::Val(); - zv::Ref rangeHelper = slot(PT_MS_PROP_CONFIGURED_PHP_VERSION_RANGE_HELPER); + if (UNEXPECTED(!requireService())) return zv::Val(); + zv::Ref rangeHelper = service(PT_MSS_CONFIGURED_PHP_VERSION_RANGE_HELPER); zv::Val range = pt_type_call(rangeHelper.asObject(), PT_LC("getversionrange"), 0, NULL); if (UNEXPECTED(range.isUndef())) return zv::Val(); /* [$minPhpVersion, $maxPhpVersion] = ... */ @@ -3975,7 +3964,7 @@ class MutatingScope return pt_type_new(PT_CLASS_PHP_VERSIONS, 1, versionRange.raw()); } - zv::Ref phpVersion = slot(PT_MS_PROP_PHP_VERSION); + zv::Ref phpVersion = service(PT_MSS_PHP_VERSION); if (UNEXPECTED(!phpVersion.isObject())) return uninitializedProperty("phpVersion"); zv::Val versionId = pt_php_version_get_version_id(phpVersion.raw()); if (UNEXPECTED(versionId.isUndef())) return zv::Val(); @@ -4099,7 +4088,7 @@ class MutatingScope if (UNEXPECTED(EG(exception))) return zv::Val(); first = &nullZv; } - zv::Ref provider = slot(PT_MS_PROP_REFLECTION_PROVIDER); + zv::Ref provider = service(PT_MSS_REFLECTION_PROVIDER); if (UNEXPECTED(!provider.isObject())) return uninitializedProperty("reflectionProvider"); bool hasClass; if (UNEXPECTED(!pt_reflection_provider_has_class(provider.asObject(), first, hasClass))) return zv::Val(); @@ -4122,7 +4111,7 @@ class MutatingScope /* $this->initializerExprTypeResolver->getFunctionType($type, $isNullable, false, $context) */ zv::Val initializerExprTypeResolverFunctionType(zval *type, bool isNullable, zval *context) { - zv::Ref resolver = slot(PT_MS_PROP_INITIALIZER_EXPR_TYPE_RESOLVER); + zv::Ref resolver = service(PT_MSS_INITIALIZER_EXPR_TYPE_RESOLVER); if (UNEXPECTED(!resolver.isObject())) return uninitializedProperty("initializerExprTypeResolver"); return pt_initializer_expr_type_resolver_get_function_type(resolver.raw(), type, isNullable, false, context); } @@ -4260,7 +4249,7 @@ class MutatingScope zv::Str ownedName = zv::Str::copyOf(name); zv::Val context = pt_initializer_expr_context_from_scope(thisZval()); if (UNEXPECTED(context.isUndef())) return zv::Val(); - zv::Ref resolver = slot(PT_MS_PROP_INITIALIZER_EXPR_TYPE_RESOLVER); + zv::Ref resolver = service(PT_MSS_INITIALIZER_EXPR_TYPE_RESOLVER); if (UNEXPECTED(!resolver.isObject())) return uninitializedProperty("initializerExprTypeResolver"); zv::Val type = pt_initializer_expr_type_resolver_get_type(resolver.raw(), defaultValue.deref().raw(), context.raw()); if (UNEXPECTED(type.isUndef())) return zv::Val(); @@ -4324,7 +4313,7 @@ class MutatingScope ZVAL_OBJ(&functionLikeZv, functionLike); zv::Val context = pt_initializer_expr_context_from_stub_parameter(className, file.raw(), &functionLikeZv); if (UNEXPECTED(context.isUndef())) return zv::Val(); - zv::Ref factory = slot(PT_MS_PROP_ATTRIBUTE_REFLECTION_FACTORY); + zv::Ref factory = service(PT_MSS_ATTRIBUTE_REFLECTION_FACTORY); if (UNEXPECTED(!factory.isObject())) return uninitializedProperty("attributeReflectionFactory"); zv::Args argv{attrGroups, context.raw()}; return pt_type_call(factory.asObject(), PT_LC("fromattrgroups"), 2, argv); @@ -5095,7 +5084,7 @@ class MutatingScope /* $this->phpVersion->() (PhpVersionAccess.cpp); false = pending exception */ [[nodiscard]] bool phpVersionQuery(pt_php_version_query query, bool &out) { - zv::Ref phpVersion = slot(PT_MS_PROP_PHP_VERSION); + zv::Ref phpVersion = service(PT_MSS_PHP_VERSION); if (UNEXPECTED(!phpVersion.isObject())) { (void) uninitializedProperty("phpVersion"); return false; @@ -5191,6 +5180,25 @@ class MutatingScope return OBJ_PROP(object, (uint32_t) offset); } + /* $other->services, deref'd; NULL with an Error pending */ + [[nodiscard]] static zval *otherServicesSlot(zend_object *object) + { + zval *services = otherProp(object, PT_MS_PROP_SERVICES, PT_LC("services")); + if (UNEXPECTED(services == NULL)) return NULL; + ZVAL_DEREF(services); + return services; + } + + /* $other->services-> of another scope object (see otherProp()); + * NULL with an Error pending when it has no $services */ + [[nodiscard]] static zval *otherService(zend_object *object, uint32_t which) + { + zval *services = otherProp(object, PT_MS_PROP_SERVICES, PT_LC("services")); + if (UNEXPECTED(services == NULL)) return NULL; + ZVAL_DEREF(services); + return pt_ms_service_of(services, which); + } + /* $other->() answering a bool; false = pending exception */ [[nodiscard]] static bool otherCallBool(zend_object *object, const char *lcname, size_t len, bool &out) { @@ -6832,7 +6840,7 @@ class MutatingScope zv::Val isFalse = pt_type_call(Z_OBJ_P(type), PT_LC("isfalse"), 0, NULL); if (UNEXPECTED(isFalse.isUndef())) return false; if (pt_type_trinary_value(isFalse.raw()) != PT_TRI_YES) return EXPECTED(EG(exception) == NULL); - zv::Ref provider = slot(PT_MS_PROP_REFLECTION_PROVIDER); + zv::Ref provider = service(PT_MSS_REFLECTION_PROVIDER); if (UNEXPECTED(!provider.isObject())) { (void) uninitializedProperty("reflectionProvider"); return false; @@ -7150,7 +7158,7 @@ class MutatingScope bool isClone = zend_string_equals_literal(lowered, "__clone"); zend_string_release(lowered); if (!isClone) return scope; - zval *phpVersion = otherProp(scopeObject, PT_MS_PROP_PHP_VERSION, PT_LC("phpVersion")); + zval *phpVersion = otherService(scopeObject, PT_MSS_PHP_VERSION); if (UNEXPECTED(phpVersion == NULL)) return zv::Val(); ZVAL_DEREF(phpVersion); if (UNEXPECTED(Z_TYPE_P(phpVersion) != IS_OBJECT)) { @@ -7175,7 +7183,7 @@ class MutatingScope zv::Val exprString = thisGetNodeKey(expressionToInvalidate); if (UNEXPECTED(exprString.isUndef())) return zv::Val(); zv::Str key = zv::Str::adopt(zval_get_string(exprString.raw())); - zv::Ref exprPrinter = slot(PT_MS_PROP_EXPR_PRINTER); + zv::Ref exprPrinter = service(PT_MSS_EXPR_PRINTER); if (UNEXPECTED(!exprPrinter.isObject())) return uninitializedProperty("exprPrinter"); if (UNEXPECTED(!requireSlot(PT_MS_PROP_EXPRESSION_TYPES, "expressionTypes") || !requireSlot(PT_MS_PROP_CONDITIONAL_EXPRESSIONS, "conditionalExpressions"))) { @@ -7237,7 +7245,7 @@ class MutatingScope if (UNEXPECTED(!isInstance(zv::Ref(&exprZv), PT_CLASS_PROPERTY_FETCH, isFetch))) return false; } if (!isFetch) return true; - zv::Ref finder = slot(PT_MS_PROP_PROPERTY_REFLECTION_FINDER); + zv::Ref finder = service(PT_MSS_PROPERTY_REFLECTION_FINDER); if (UNEXPECTED(!finder.isObject())) { (void) uninitializedProperty("propertyReflectionFinder"); return false; @@ -7270,7 +7278,7 @@ class MutatingScope /* private (twin 3863) */ zv::Val invalidateMethodsOnExpression(zend_object *expressionToInvalidate) { - zv::Ref exprPrinter = slot(PT_MS_PROP_EXPR_PRINTER); + zv::Ref exprPrinter = service(PT_MSS_EXPR_PRINTER); if (UNEXPECTED(!exprPrinter.isObject())) return uninitializedProperty("exprPrinter"); zval exprZv; ZVAL_OBJ(&exprZv, expressionToInvalidate); @@ -7549,7 +7557,7 @@ class MutatingScope /* (twin 3993 / 4003) */ zv::Val filterByValue(zend_object *expr, bool truthy) { - zv::Ref typeSpecifier = slot(PT_MS_PROP_TYPE_SPECIFIER); + zv::Ref typeSpecifier = service(PT_MSS_TYPE_SPECIFIER); if (UNEXPECTED(!typeSpecifier.isObject())) return uninitializedProperty("typeSpecifier"); /* the singleton, borrowed: the context registry holds it */ zend_object *context = truthy ? pt_type_specifier_context_create_truthy() : pt_type_specifier_context_create_falsey(); @@ -8640,7 +8648,7 @@ class MutatingScope if (UNEXPECTED(className.isUndef())) return zv::Val(); zv::Val constantName = pt_name_node_to_string(nameNode.deref().raw()); if (UNEXPECTED(constantName.isUndef())) return zv::Val(); - zv::Ref constantResolver = slot(PT_MS_PROP_CONSTANT_RESOLVER); + zv::Ref constantResolver = service(PT_MSS_CONSTANT_RESOLVER); if (UNEXPECTED(!constantResolver.isObject())) { (void) uninitializedProperty("constantResolver"); return zv::Val(); @@ -9288,7 +9296,7 @@ class MutatingScope zv::Arr generalizedExpressions = zv::Arr::create(0); zv::Arr newVariableTypeHolders = zv::Arr::create(0); - zv::Ref exprPrinter = slot(PT_MS_PROP_EXPR_PRINTER); + zv::Ref exprPrinter = service(PT_MSS_EXPR_PRINTER); if (UNEXPECTED(!exprPrinter.isObject())) return uninitializedProperty("exprPrinter"); for (const SortedEntry &entry : sorted) { zv::Str variableExprString = entryKey(entry.key, entry.index); @@ -9390,7 +9398,7 @@ class MutatingScope zend_throw_error(NULL, "Call to a member function getGreaterOrEqualType() on %s", zend_zval_value_name(size.raw())); return false; } - zv::Ref phpVersion = slot(PT_MS_PROP_PHP_VERSION); + zv::Ref phpVersion = service(PT_MSS_PHP_VERSION); if (UNEXPECTED(!phpVersion.isObject())) { (void) uninitializedProperty("phpVersion"); return false; @@ -10111,7 +10119,7 @@ class MutatingScope if (!isProtectedSet) return canAccessClassMember(propertyReflection, out); } - zv::Ref phpVersion = slot(PT_MS_PROP_PHP_VERSION); + zv::Ref phpVersion = service(PT_MSS_PHP_VERSION); if (UNEXPECTED(!phpVersion.isObject())) { (void) uninitializedProperty("phpVersion"); return false; @@ -10173,7 +10181,7 @@ class MutatingScope (void) uninitializedProperty("inClosureBindScopeClasses"); return false; } - zv::Ref reflectionProvider = slot(PT_MS_PROP_REFLECTION_PROVIDER); + zv::Ref reflectionProvider = service(PT_MSS_REFLECTION_PROVIDER); if (UNEXPECTED(!reflectionProvider.isObject())) { (void) uninitializedProperty("reflectionProvider"); return false; @@ -10531,7 +10539,7 @@ class MutatingScope /* (twin 5755) */ zv::Val getConstantExplicitTypeFromConfig(zend_string *constantName, zval *constantType) { - zv::Ref constantResolver = slot(PT_MS_PROP_CONSTANT_RESOLVER); + zv::Ref constantResolver = service(PT_MSS_CONSTANT_RESOLVER); if (UNEXPECTED(!constantResolver.isObject())) return uninitializedProperty("constantResolver"); zv::Args args{constantName, constantType}; return pt_type_call(constantResolver.asObject(), PT_LC("resolveconstanttype"), 2, args); @@ -10559,7 +10567,7 @@ class MutatingScope /* (twin 5858) */ bool invokeNodeCallback(zend_object *node) { - zv::Ref nodeCallback = slot(PT_MS_PROP_NODE_CALLBACK); + zv::Ref nodeCallback = service(PT_MSS_NODE_CALLBACK); if (UNEXPECTED(nodeCallback.isUndef())) { (void) uninitializedProperty("nodeCallback"); return false; @@ -10576,7 +10584,7 @@ class MutatingScope /* (twin 5874) */ bool emitCollectedData(zend_string *collectorType, zval *data) { - zv::Ref nodeCallback = slot(PT_MS_PROP_NODE_CALLBACK); + zv::Ref nodeCallback = service(PT_MSS_NODE_CALLBACK); if (UNEXPECTED(nodeCallback.isUndef())) { (void) uninitializedProperty("nodeCallback"); return false; @@ -10634,7 +10642,7 @@ class MutatingScope /* the collector's method (lowercase name) with the arguments, the scope and whether it is inside the walk */ bool callValueDependencyCollector(const char *method, size_t methodLength, zval *first, zval *second) { - zv::Ref nodeCallback = slot(PT_MS_PROP_NODE_CALLBACK); + zv::Ref nodeCallback = service(PT_MSS_NODE_CALLBACK); if (UNEXPECTED(nodeCallback.isUndef())) { (void) uninitializedProperty("nodeCallback"); return false; @@ -10670,7 +10678,7 @@ class MutatingScope zv::Val getNodeKey(zend_object *node) { - zv::Ref exprPrinter = slot(PT_MS_PROP_EXPR_PRINTER); + zv::Ref exprPrinter = service(PT_MSS_EXPR_PRINTER); if (UNEXPECTED(!exprPrinter.isObject())) return uninitializedProperty("exprPrinter"); zend_string *key = pt_node_key(node, exprPrinter.raw()); if (UNEXPECTED(key == NULL)) return zv::Val(); @@ -10678,11 +10686,11 @@ class MutatingScope } /** @internal */ - zv::Val getExprPrinter() const { return copyOfSlot(PT_MS_PROP_EXPR_PRINTER); } + zv::Val getExprPrinter() const { return zv::Val::copyOf(service(PT_MSS_EXPR_PRINTER)); } zv::Val hasExpressionType(zend_object *node) { - zv::Ref exprPrinter = slot(PT_MS_PROP_EXPR_PRINTER); + zv::Ref exprPrinter = service(PT_MSS_EXPR_PRINTER); if (UNEXPECTED(!exprPrinter.isObject())) return uninitializedProperty("exprPrinter"); return pt_scope_ops_has_expression_type(thisZval(), node, exprPrinter.raw()); } @@ -10972,7 +10980,7 @@ class MutatingScope if (UNEXPECTED(!isInstance(zv::Ref(&exprZv), PT_CLASS_CONST_FETCH, isConstantExpr))) return zv::Val(); } if (isConstantExpr) { - zv::Ref resolver = slot(PT_MS_PROP_INITIALIZER_EXPR_TYPE_RESOLVER); + zv::Ref resolver = service(PT_MSS_INITIALIZER_EXPR_TYPE_RESOLVER); if (UNEXPECTED(!resolver.isObject())) return uninitializedProperty("initializerExprTypeResolver"); zval selfZv; ZVAL_OBJ(&selfZv, self); @@ -11239,6 +11247,7 @@ namespace pt_ms { inline constexpr const char *self = "PHPStan\\Analyser\\MutatingScope"; inline constexpr const char *container = "PHPStan\\DependencyInjection\\Container"; inline constexpr const char *internalScopeFactory = "PHPStan\\Analyser\\InternalScopeFactory"; +inline constexpr const char *scopeServices = "PHPStan\\Analyser\\ScopeServices"; inline constexpr const char *reflectionProvider = "PHPStan\\Reflection\\ReflectionProvider"; inline constexpr const char *initializerExprTypeResolver = "PHPStan\\Reflection\\InitializerExprTypeResolver"; inline constexpr const char *extensionsCollection = "PHPStan\\DependencyInjection\\ExtensionsCollection"; @@ -12424,6 +12433,16 @@ zv::Val pt_mutating_scope_after_open_ssl_call(zend_object *scope, zend_string *o /* }}} */ +/* $scope->services->exprPrinter for ScopeOps (the native class's slot, the + * property by name on another class); NULL with an Error pending */ +zval *pt_mutating_scope_expr_printer(zval *scope) +{ + zend_object *object = Z_OBJ_P(scope); + zval *services = phpstanturbo::MutatingScope::otherServicesSlot(object); + if (UNEXPECTED(services == NULL)) return NULL; + return pt_ms_service_of(services, PT_MSS_EXPR_PRINTER); +} + static HashTable *pt_ms_custom_serialization_methods_list = nullptr; static void pt_ms_custom_serialization_methods_constant(zval *out) @@ -12450,22 +12469,9 @@ PT_MINIT_REGISTRATION(pt_register_mutating_scope) cls.property("namespace", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, MAY_BE_STRING | MAY_BE_NULL); cls.property("scopeOutOfFirstLevelStatement", ZEND_ACC_PRIVATE, reg::PropertyKind::TypedNull, MAY_BE_NULL, "self"); cls.property("scopeWithPromotedNativeTypes", ZEND_ACC_PRIVATE, reg::PropertyKind::TypedNull, MAY_BE_NULL, "self"); - cls.property("container", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, 0, container); + cls.property("services", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, 0, scopeServices); cls.property("scopeFactory", ZEND_ACC_PROTECTED, reg::PropertyKind::Typed, 0, internalScopeFactory); - cls.property("reflectionProvider", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, 0, reflectionProvider); - cls.property("initializerExprTypeResolver", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, 0, initializerExprTypeResolver); - cls.property("expressionTypeResolverExtensions", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, 0, extensionsCollection); - cls.property("exprPrinter", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, 0, exprPrinter); - cls.property("typeSpecifier", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, 0, typeSpecifier); - cls.property("propertyReflectionFinder", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, 0, propertyReflectionFinder); - cls.property("parser", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, 0, parser); - cls.property("constantResolver", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, 0, constantResolver); - cls.property("expressionResultStorageStack", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, 0, expressionResultStorageStack); cls.property("context", ZEND_ACC_PROTECTED, reg::PropertyKind::Typed, 0, scopeContext); - cls.property("phpVersion", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, 0, phpVersion); - cls.property("attributeReflectionFactory", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, 0, attributeReflectionFactory); - cls.property("configuredPhpVersionRangeHelper", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, 0, configuredPhpVersionRangeHelper); - cls.property("nodeCallback", ZEND_ACC_PRIVATE, reg::PropertyKind::Null, 0); cls.property("declareStrictTypes", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, MAY_BE_BOOL); cls.property("function", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, MAY_BE_NULL, phpFunctionFromParserNodeReflection); cls.property("expressionTypes", ZEND_ACC_PUBLIC, reg::PropertyKind::Typed, MAY_BE_ARRAY); @@ -12494,23 +12500,10 @@ PT_MINIT_REGISTRATION(pt_register_mutating_scope) cls.privateClassConstantValue("CUSTOM_SERIALIZATION_METHODS", pt_ms_custom_serialization_methods_constant); /* }}} */ - cls.method("__construct", reg::Public, 15, { - reg::obj("container", container), + cls.method("__construct", reg::Public, 3, { + reg::obj("services", scopeServices), reg::obj("scopeFactory", internalScopeFactory), - reg::obj("reflectionProvider", reflectionProvider), - reg::obj("initializerExprTypeResolver", initializerExprTypeResolver), - reg::obj("expressionTypeResolverExtensions", extensionsCollection), - reg::obj("exprPrinter", exprPrinter), - reg::obj("typeSpecifier", typeSpecifier), - reg::obj("propertyReflectionFinder", propertyReflectionFinder), - reg::obj("parser", parser), - reg::obj("constantResolver", constantResolver), - reg::obj("expressionResultStorageStack", expressionResultStorageStack), reg::obj("context", scopeContext), - reg::obj("phpVersion", phpVersion), - reg::obj("attributeReflectionFactory", attributeReflectionFactory), - reg::obj("configuredPhpVersionRangeHelper", configuredPhpVersionRangeHelper), - reg::withDefault(reg::any("nodeCallback"), "null"), reg::withDefault(reg::boolArg("declareStrictTypes"), "false"), reg::withDefault(reg::obj("function", phpFunctionFromParserNodeReflection, true), "null"), reg::withDefault(reg::stringArg("namespace", true), "null"), @@ -12531,24 +12524,11 @@ PT_MINIT_REGISTRATION(pt_register_mutating_scope) }, [](INTERNAL_FUNCTION_PARAMETERS) { MutatingScope::ConstructArgs a = {}; a.inFirstLevelStatement = true; - ZEND_PARSE_PARAMETERS_START(15, 33) - Z_PARAM_OBJECT(a.container) + ZEND_PARSE_PARAMETERS_START(3, 20) + Z_PARAM_OBJECT(a.services) Z_PARAM_OBJECT(a.scopeFactory) - Z_PARAM_OBJECT(a.reflectionProvider) - Z_PARAM_OBJECT(a.initializerExprTypeResolver) - Z_PARAM_OBJECT(a.expressionTypeResolverExtensions) - Z_PARAM_OBJECT(a.exprPrinter) - Z_PARAM_OBJECT(a.typeSpecifier) - Z_PARAM_OBJECT(a.propertyReflectionFinder) - Z_PARAM_OBJECT(a.parser) - Z_PARAM_OBJECT(a.constantResolver) - Z_PARAM_OBJECT(a.expressionResultStorageStack) Z_PARAM_OBJECT(a.context) - Z_PARAM_OBJECT(a.phpVersion) - Z_PARAM_OBJECT(a.attributeReflectionFactory) - Z_PARAM_OBJECT(a.configuredPhpVersionRangeHelper) Z_PARAM_OPTIONAL - Z_PARAM_ZVAL(a.nodeCallback) Z_PARAM_BOOL(a.declareStrictTypes) Z_PARAM_OBJECT_OR_NULL(a.function) Z_PARAM_STR_OR_NULL(a.ns) @@ -12567,9 +12547,6 @@ PT_MINIT_REGISTRATION(pt_register_mutating_scope) Z_PARAM_OBJECT_OR_NULL(a.templateArgumentFrame) Z_PARAM_OBJECT_OR_NULL(a.templateArgumentConstraints) ZEND_PARSE_PARAMETERS_END(); - if (a.nodeCallback != NULL) { - ZVAL_DEREF(a.nodeCallback); - } PT_THIS.construct(a); }); diff --git a/turbo-ext/src/ScopeOps.cpp b/turbo-ext/src/ScopeOps.cpp index 090c1786847..e537a059053 100644 --- a/turbo-ext/src/ScopeOps.cpp +++ b/turbo-ext/src/ScopeOps.cpp @@ -145,7 +145,7 @@ class ScopeOps { *keyOut = NULL; - zval *exprPrinter = scopeProp(scope, "exprPrinter", sizeof("exprPrinter") - 1); + zval *exprPrinter = pt_mutating_scope_expr_printer(scope); if (UNEXPECTED(exprPrinter == NULL)) return zv::Val(); if (UNEXPECTED(Z_TYPE_P(exprPrinter) != IS_OBJECT)) { zend_throw_error(NULL, "phpstan_turbo: exprPrinter is not an object"); diff --git a/turbo-ext/src/generated/MutatingScope.h b/turbo-ext/src/generated/MutatingScope.h index 832eb9a9226..2edb0591af6 100644 --- a/turbo-ext/src/generated/MutatingScope.h +++ b/turbo-ext/src/generated/MutatingScope.h @@ -15,38 +15,25 @@ inline constexpr uint32_t nodeCallbackScope = 1; inline constexpr uint32_t namespace_ = 2; inline constexpr uint32_t scopeOutOfFirstLevelStatement = 3; inline constexpr uint32_t scopeWithPromotedNativeTypes = 4; -inline constexpr uint32_t container = 5; +inline constexpr uint32_t services = 5; inline constexpr uint32_t scopeFactory = 6; -inline constexpr uint32_t reflectionProvider = 7; -inline constexpr uint32_t initializerExprTypeResolver = 8; -inline constexpr uint32_t expressionTypeResolverExtensions = 9; -inline constexpr uint32_t exprPrinter = 10; -inline constexpr uint32_t typeSpecifier = 11; -inline constexpr uint32_t propertyReflectionFinder = 12; -inline constexpr uint32_t parser = 13; -inline constexpr uint32_t constantResolver = 14; -inline constexpr uint32_t expressionResultStorageStack = 15; -inline constexpr uint32_t context = 16; -inline constexpr uint32_t phpVersion = 17; -inline constexpr uint32_t attributeReflectionFactory = 18; -inline constexpr uint32_t configuredPhpVersionRangeHelper = 19; -inline constexpr uint32_t nodeCallback = 20; -inline constexpr uint32_t declareStrictTypes = 21; -inline constexpr uint32_t function = 22; -inline constexpr uint32_t expressionTypes = 23; -inline constexpr uint32_t nativeExpressionTypes = 24; -inline constexpr uint32_t conditionalExpressions = 25; -inline constexpr uint32_t inClosureBindScopeClasses = 26; -inline constexpr uint32_t anonymousFunctionReflection = 27; -inline constexpr uint32_t inFirstLevelStatement = 28; -inline constexpr uint32_t currentlyAssignedExpressions = 29; -inline constexpr uint32_t currentlyAllowedUndefinedExpressions = 30; -inline constexpr uint32_t inFunctionCallsStack = 31; -inline constexpr uint32_t afterExtractCall = 32; -inline constexpr uint32_t parentScope = 33; -inline constexpr uint32_t nativeTypesPromoted = 34; -inline constexpr uint32_t templateArgumentFrame = 35; -inline constexpr uint32_t templateArgumentConstraints = 36; +inline constexpr uint32_t context = 7; +inline constexpr uint32_t declareStrictTypes = 8; +inline constexpr uint32_t function = 9; +inline constexpr uint32_t expressionTypes = 10; +inline constexpr uint32_t nativeExpressionTypes = 11; +inline constexpr uint32_t conditionalExpressions = 12; +inline constexpr uint32_t inClosureBindScopeClasses = 13; +inline constexpr uint32_t anonymousFunctionReflection = 14; +inline constexpr uint32_t inFirstLevelStatement = 15; +inline constexpr uint32_t currentlyAssignedExpressions = 16; +inline constexpr uint32_t currentlyAllowedUndefinedExpressions = 17; +inline constexpr uint32_t inFunctionCallsStack = 18; +inline constexpr uint32_t afterExtractCall = 19; +inline constexpr uint32_t parentScope = 20; +inline constexpr uint32_t nativeTypesPromoted = 21; +inline constexpr uint32_t templateArgumentFrame = 22; +inline constexpr uint32_t templateArgumentConstraints = 23; } // namespace slot inline void declareClass(reg::Class &cls) @@ -63,22 +50,9 @@ inline void declareProperties(reg::Class &cls) cls.property("namespace", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, MAY_BE_NULL | MAY_BE_STRING); cls.property("scopeOutOfFirstLevelStatement", ZEND_ACC_PRIVATE, reg::PropertyKind::TypedNull, MAY_BE_NULL, "PHPStan\\Analyser\\MutatingScope"); cls.property("scopeWithPromotedNativeTypes", ZEND_ACC_PRIVATE, reg::PropertyKind::TypedNull, MAY_BE_NULL, "PHPStan\\Analyser\\MutatingScope"); - cls.property("container", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, 0, "PHPStan\\DependencyInjection\\Container"); + cls.property("services", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, 0, "PHPStan\\Analyser\\ScopeServices"); cls.property("scopeFactory", ZEND_ACC_PROTECTED, reg::PropertyKind::Typed, 0, "PHPStan\\Analyser\\InternalScopeFactory"); - cls.property("reflectionProvider", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, 0, "PHPStan\\Reflection\\ReflectionProvider"); - cls.property("initializerExprTypeResolver", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, 0, "PHPStan\\Reflection\\InitializerExprTypeResolver"); - cls.property("expressionTypeResolverExtensions", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, 0, "PHPStan\\DependencyInjection\\ExtensionsCollection"); - cls.property("exprPrinter", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, 0, "PHPStan\\Node\\Printer\\ExprPrinter"); - cls.property("typeSpecifier", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, 0, "PHPStan\\Analyser\\TypeSpecifier"); - cls.property("propertyReflectionFinder", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, 0, "PHPStan\\Rules\\Properties\\PropertyReflectionFinder"); - cls.property("parser", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, 0, "PHPStan\\Parser\\Parser"); - cls.property("constantResolver", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, 0, "PHPStan\\Analyser\\ConstantResolver"); - cls.property("expressionResultStorageStack", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, 0, "PHPStan\\Analyser\\ExpressionResultStorageStack"); cls.property("context", ZEND_ACC_PROTECTED, reg::PropertyKind::Typed, 0, "PHPStan\\Analyser\\ScopeContext"); - cls.property("phpVersion", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, 0, "PHPStan\\Php\\PhpVersion"); - cls.property("attributeReflectionFactory", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, 0, "PHPStan\\Reflection\\AttributeReflectionFactory"); - cls.property("configuredPhpVersionRangeHelper", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, 0, "PHPStan\\Php\\ConfiguredPhpVersionRangeHelper"); - cls.property("nodeCallback", ZEND_ACC_PRIVATE, reg::PropertyKind::Null, 0); cls.property("declareStrictTypes", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, MAY_BE_BOOL); cls.property("function", ZEND_ACC_PRIVATE, reg::PropertyKind::Typed, MAY_BE_NULL, "PHPStan\\Reflection\\Php\\PhpFunctionFromParserNodeReflection"); cls.property("expressionTypes", ZEND_ACC_PUBLIC, reg::PropertyKind::Typed, MAY_BE_ARRAY); @@ -100,1198 +74,1161 @@ inline void declareProperties(reg::Class &cls) /* the string and parameter tables the signatures below index into (see reg::Sig) */ namespace sigtab { inline constexpr char strings[] = - "container\0" /* 0 */ - "PHPStan\\DependencyInjection\\Container\0" /* 10 */ - "scopeFactory\0" /* 48 */ - "PHPStan\\Analyser\\InternalScopeFactory\0" /* 61 */ - "reflectionProvider\0" /* 99 */ - "PHPStan\\Reflection\\ReflectionProvider\0" /* 118 */ - "initializerExprTypeResolver\0" /* 156 */ - "PHPStan\\Reflection\\InitializerExprTypeResolver\0" /* 184 */ - "expressionTypeResolverExtensions\0" /* 231 */ - "PHPStan\\DependencyInjection\\ExtensionsCollection\0" /* 264 */ - "exprPrinter\0" /* 313 */ - "PHPStan\\Node\\Printer\\ExprPrinter\0" /* 325 */ - "typeSpecifier\0" /* 358 */ - "PHPStan\\Analyser\\TypeSpecifier\0" /* 372 */ - "propertyReflectionFinder\0" /* 403 */ - "PHPStan\\Rules\\Properties\\PropertyReflectionFinder\0" /* 428 */ - "parser\0" /* 478 */ - "PHPStan\\Parser\\Parser\0" /* 485 */ - "constantResolver\0" /* 507 */ - "PHPStan\\Analyser\\ConstantResolver\0" /* 524 */ - "expressionResultStorageStack\0" /* 558 */ - "PHPStan\\Analyser\\ExpressionResultStorageStack\0" /* 587 */ - "context\0" /* 633 */ - "PHPStan\\Analyser\\ScopeContext\0" /* 641 */ - "phpVersion\0" /* 671 */ - "PHPStan\\Php\\PhpVersion\0" /* 682 */ - "attributeReflectionFactory\0" /* 705 */ - "PHPStan\\Reflection\\AttributeReflectionFactory\0" /* 732 */ - "configuredPhpVersionRangeHelper\0" /* 778 */ - "PHPStan\\Php\\ConfiguredPhpVersionRangeHelper\0" /* 810 */ - "nodeCallback\0" /* 854 */ - "null\0" /* 867 */ - "declareStrictTypes\0" /* 872 */ - "false\0" /* 891 */ - "function\0" /* 897 */ - "PHPStan\\Reflection\\Php\\PhpFunctionFromParserNodeReflection\0" /* 906 */ - "namespace\0" /* 965 */ - "expressionTypes\0" /* 975 */ - "[]\0" /* 991 */ - "nativeExpressionTypes\0" /* 994 */ - "conditionalExpressions\0" /* 1016 */ - "inClosureBindScopeClasses\0" /* 1039 */ - "anonymousFunctionReflection\0" /* 1065 */ - "PHPStan\\Type\\ClosureType\0" /* 1093 */ - "inFirstLevelStatement\0" /* 1118 */ - "true\0" /* 1140 */ - "currentlyAssignedExpressions\0" /* 1145 */ - "currentlyAllowedUndefinedExpressions\0" /* 1174 */ - "inFunctionCallsStack\0" /* 1211 */ - "afterExtractCall\0" /* 1232 */ - "parentScope\0" /* 1249 */ - "PHPStan\\Analyser\\MutatingScope\0" /* 1261 */ - "nativeTypesPromoted\0" /* 1292 */ - "templateArgumentFrame\0" /* 1312 */ - "PHPStan\\Analyser\\Generics\\TemplateArgumentFrame\0" /* 1334 */ - "templateArgumentConstraints\0" /* 1382 */ - "PHPStan\\Analyser\\Generics\\TemplateArgumentConstraints\0" /* 1410 */ - "__construct\0" /* 1464 */ - "\0" /* 1476 */ - "toNodeCallbackScope\0" /* 1477 */ - "toWalkScope\0" /* 1497 */ - "toMutatingScope\0" /* 1509 */ - "getFile\0" /* 1525 */ - "getFileDescription\0" /* 1533 */ - "isDeclareStrictTypes\0" /* 1552 */ - "enterDeclareStrictTypes\0" /* 1573 */ - "currentExpressionTypes\0" /* 1597 */ - "rememberConstructorExpressions\0" /* 1620 */ - "classHasCustomSerialization\0" /* 1651 */ - "rememberConstructorScope\0" /* 1679 */ - "expr\0" /* 1704 */ - "PhpParser\\Node\\Expr\\PropertyFetch\0" /* 1709 */ - "allowOnlyOnThis\0" /* 1743 */ - "isReadonlyPropertyFetch\0" /* 1759 */ - "isInClass\0" /* 1783 */ - "isInTrait\0" /* 1793 */ - "PHPStan\\Reflection\\ClassReflection\0" /* 1803 */ - "getClassReflection\0" /* 1838 */ - "getTraitReflection\0" /* 1857 */ - "getFunction\0" /* 1876 */ - "getFunctionName\0" /* 1888 */ - "getNamespace\0" /* 1904 */ - "getParentScope\0" /* 1917 */ - "canAnyVariableExist\0" /* 1932 */ - "afterClearstatcacheCall\0" /* 1952 */ - "openSslFunctionName\0" /* 1976 */ - "afterOpenSslCall\0" /* 1996 */ - "invalidateVolatileExpressions\0" /* 2013 */ - "functionNames\0" /* 2043 */ - "declaredSymbolName\0" /* 2057 */ - "invalidateExistenceCheckExpressions\0" /* 2076 */ - "variableName\0" /* 2112 */ - "PHPStan\\TrinaryLogic\0" /* 2125 */ - "hasVariableType\0" /* 2146 */ - "PHPStan\\Type\\Type\0" /* 2162 */ - "getVariableType\0" /* 2180 */ - "getDefinedVariables\0" /* 2196 */ - "getMaybeDefinedVariables\0" /* 2216 */ - "PhpParser\\Node\\Expr\0" /* 2241 */ - "findPossiblyImpureCallDescriptions\0" /* 2261 */ - "isGlobalVariable\0" /* 2296 */ - "name\0" /* 2313 */ - "PhpParser\\Node\\Name\0" /* 2318 */ - "hasConstant\0" /* 2338 */ - "fileHasCompilerHaltStatementCalls\0" /* 2350 */ - "isInAnonymousFunction\0" /* 2384 */ - "getAnonymousFunctionReflection\0" /* 2406 */ - "getAnonymousFunctionReturnType\0" /* 2437 */ - "withAnonymousFunctionReflection\0" /* 2468 */ - "node\0" /* 2500 */ - "getType\0" /* 2505 */ - "getScopeType\0" /* 2513 */ - "getScopeNativeType\0" /* 2526 */ - "getNodeKey\0" /* 2545 */ - "getExprPrinter\0" /* 2556 */ - "duplicateWith\0" /* 2571 */ - "relevantRoots\0" /* 2585 */ - "getClosureScopeCacheKey\0" /* 2599 */ - "exprString\0" /* 2623 */ - "roots\0" /* 2634 */ - "exprStringIsRootedIn\0" /* 2640 */ - "resolveType\0" /* 2661 */ - "resolveTypeOfNewWorldHandlerNode\0" /* 2673 */ - "getCurrentTypesOfSpecifiedExpr\0" /* 2706 */ - "PHPStan\\Analyser\\TypeSpecifierContext\0" /* 2737 */ - "PHPStan\\Analyser\\SpecifiedTypes\0" /* 2775 */ - "specifyTypesOfNewWorldHandlerNode\0" /* 2807 */ - "PHPStan\\Analyser\\ExpressionResult\0" /* 2841 */ - "obtainResultForNode\0" /* 2875 */ - "storage\0" /* 2895 */ - "PHPStan\\Analyser\\ExpressionResultStorage\0" /* 2903 */ - "pushExpressionResultStorage\0" /* 2944 */ - "popExpressionResultStorage\0" /* 2972 */ - "findSettledStoredResult\0" /* 2999 */ - "getCurrentExpressionResultStorage\0" /* 3023 */ - "frame\0" /* 3057 */ - "withTemplateArgumentFrame\0" /* 3063 */ - "getCurrentTemplateArgumentFrame\0" /* 3089 */ - "getTemplateArgumentConstraints\0" /* 3121 */ - "constraints\0" /* 3152 */ - "withTemplateArgumentConstraints\0" /* 3164 */ - "addTemplateArgumentConstraints\0" /* 3196 */ - "withoutMemoizedTypes\0" /* 3227 */ - "other\0" /* 3248 */ - "getDifferingVariableRoots\0" /* 3254 */ - "key\0" /* 3280 */ - "getVariablesOfExpressionKey\0" /* 3284 */ - "recordedEntry\0" /* 3312 */ - "recordedExit\0" /* 3326 */ - "withRecordedStatementDelta\0" /* 3339 */ - "current\0" /* 3366 */ - "applyRecordedHolderDelta\0" /* 3374 */ - "getNativeType\0" /* 3399 */ - "getKeepVoidType\0" /* 3413 */ - "doNotTreatPhpDocTypesAsCertain\0" /* 3429 */ - "promoteNativeTypes\0" /* 3460 */ - "resolveName\0" /* 3479 */ - "PHPStan\\Type\\TypeWithClassName\0" /* 3491 */ - "resolveTypeByName\0" /* 3522 */ - "value\0" /* 3540 */ - "getTypeFromValue\0" /* 3546 */ - "hasExpressionType\0" /* 3563 */ - "getTrackedExpressionType\0" /* 3581 */ - "reflection\0" /* 3606 */ - "parameter\0" /* 3617 */ - "PHPStan\\Reflection\\ParameterReflection\0" /* 3627 */ - "rememberTypes\0" /* 3666 */ - "pushInFunctionCall\0" /* 3680 */ - "popInFunctionCall\0" /* 3699 */ - "className\0" /* 3717 */ - "isInClassExists\0" /* 3727 */ - "getFunctionCallStack\0" /* 3743 */ - "getFunctionCallStackWithParameters\0" /* 3764 */ - "functionName\0" /* 3799 */ - "isInFunctionExists\0" /* 3812 */ - "classReflection\0" /* 3831 */ - "enterClass\0" /* 3847 */ - "traitReflection\0" /* 3858 */ - "enterTrait\0" /* 3874 */ - "classMethod\0" /* 3885 */ - "PhpParser\\Node\\Stmt\\ClassMethod\0" /* 3897 */ - "templateTypeMap\0" /* 3929 */ - "PHPStan\\Type\\Generic\\TemplateTypeMap\0" /* 3945 */ - "phpDocParameterTypes\0" /* 3982 */ - "phpDocReturnType\0" /* 4003 */ - "throwType\0" /* 4020 */ - "deprecatedDescription\0" /* 4030 */ - "isDeprecated\0" /* 4052 */ - "isInternal\0" /* 4065 */ - "isFinal\0" /* 4076 */ - "isPure\0" /* 4084 */ - "acceptsNamedArguments\0" /* 4091 */ - "asserts\0" /* 4113 */ - "PHPStan\\Reflection\\Assertions\0" /* 4121 */ - "selfOutType\0" /* 4151 */ - "phpDocComment\0" /* 4163 */ - "parameterOutTypes\0" /* 4177 */ - "immediatelyInvokedCallableParameters\0" /* 4195 */ - "phpDocClosureThisTypeParameters\0" /* 4232 */ - "isConstructor\0" /* 4264 */ - "resolvedPhpDocBlock\0" /* 4278 */ - "PHPStan\\PhpDoc\\ResolvedPhpDocBlock\0" /* 4298 */ - "phpDocPureUnlessCallableIsImpureParameters\0" /* 4333 */ - "phpDocPureUnlessParameterPassedParameters\0" /* 4376 */ - "enterClassMethod\0" /* 4418 */ - "hook\0" /* 4435 */ - "PhpParser\\Node\\PropertyHook\0" /* 4440 */ - "propertyName\0" /* 4468 */ - "nativePropertyTypeNode\0" /* 4481 */ - "PhpParser\\Node\\Identifier|PhpParser\\Node\\Name|PhpParser\\Node\\ComplexType\0" /* 4504 */ - "phpDocPropertyType\0" /* 4577 */ - "enterPropertyHook\0" /* 4596 */ - "type\0" /* 4614 */ - "transformStaticType\0" /* 4619 */ - "functionLike\0" /* 4639 */ - "PhpParser\\Node\\FunctionLike\0" /* 4652 */ - "getRealParameterTypes\0" /* 4680 */ - "getRealParameterDefaultValues\0" /* 4702 */ - "PhpParser\\Node\\Stmt\\ClassMethod|PhpParser\\Node\\Stmt\\Function_|PhpParser\\Node\\PropertyHook\0" /* 4732 */ - "getParameterAttributes\0" /* 4822 */ - "PhpParser\\Node\\Stmt\\Function_\0" /* 4845 */ - "pureUnlessCallableIsImpureParameters\0" /* 4875 */ - "pureUnlessParameterPassedParameters\0" /* 4912 */ - "enterFunction\0" /* 4948 */ - "functionReflection\0" /* 4962 */ - "preserveConstructorScope\0" /* 4981 */ - "enterFunctionLike\0" /* 5006 */ - "namespaceName\0" /* 5024 */ - "enterNamespace\0" /* 5038 */ - "thisType\0" /* 5053 */ - "nativeThisType\0" /* 5062 */ - "scopeClasses\0" /* 5077 */ - "enterClosureBind\0" /* 5090 */ - "originalScope\0" /* 5107 */ - "restoreOriginalScopeAfterClosureBind\0" /* 5121 */ - "restoreThisScope\0" /* 5158 */ - "restoreThis\0" /* 5175 */ - "enterClosureCall\0" /* 5187 */ - "isInClosureBind\0" /* 5204 */ - "withClosureBindScopeClasses\0" /* 5220 */ - "closure\0" /* 5248 */ - "PhpParser\\Node\\Expr\\Closure\0" /* 5256 */ - "callableParameters\0" /* 5284 */ - "nativeCallableParameters\0" /* 5303 */ - "enterAnonymousFunction\0" /* 5328 */ - "enterAnonymousFunctionWithoutReflection\0" /* 5351 */ - "typeHolder\0" /* 5391 */ - "PHPStan\\Analyser\\ExpressionTypeHolder\0" /* 5402 */ - "expressionTypeIsUnchangeable\0" /* 5440 */ - "invalidateStaticExpressions\0" /* 5469 */ - "arrowFunction\0" /* 5497 */ - "PhpParser\\Node\\Expr\\ArrowFunction\0" /* 5511 */ - "enterArrowFunction\0" /* 5545 */ - "enterArrowFunctionWithoutReflection\0" /* 5564 */ - "PhpParser\\Node\\Param\0" /* 5600 */ - "isParameterValueNullable\0" /* 5621 */ - "isNullable\0" /* 5646 */ - "isVariadic\0" /* 5657 */ - "getFunctionType\0" /* 5668 */ - "index\0" /* 5684 */ - "getCallableParameterType\0" /* 5690 */ - "startIndex\0" /* 5715 */ - "buildVariadicArrayTypeFromCallableParameters\0" /* 5726 */ - "nativeType\0" /* 5771 */ - "inferredType\0" /* 5782 */ - "intersectButNotNever\0" /* 5795 */ - "PhpParser\\Node\\Expr\\Match_\0" /* 5816 */ - "condType\0" /* 5843 */ - "condNativeType\0" /* 5852 */ - "enterMatch\0" /* 5867 */ - "iteratee\0" /* 5878 */ - "iterateeType\0" /* 5887 */ - "nativeIterateeType\0" /* 5900 */ - "valueName\0" /* 5919 */ - "keyName\0" /* 5929 */ - "valueByRef\0" /* 5937 */ - "enterForeach\0" /* 5948 */ - "enterForeachKey\0" /* 5961 */ - "catchType\0" /* 5977 */ - "enterCatchType\0" /* 5987 */ - "isPlainWrite\0" /* 6002 */ - "enterExpressionAssign\0" /* 6015 */ - "exitExpressionAssign\0" /* 6037 */ - "isInExpressionAssign\0" /* 6058 */ - "isInWriteExpressionAssign\0" /* 6079 */ - "setAllowedUndefinedExpression\0" /* 6105 */ - "unsetAllowedUndefinedExpression\0" /* 6135 */ - "isUndefinedExpressionAllowed\0" /* 6167 */ - "certainty\0" /* 6196 */ - "intertwinedPropagatedFrom\0" /* 6206 */ - "assignVariable\0" /* 6232 */ - "overwriteExpression\0" /* 6247 */ - "scope\0" /* 6267 */ - "rootType\0" /* 6273 */ - "assignedExpr\0" /* 6282 */ - "rootVariableName\0" /* 6295 */ - "native\0" /* 6312 */ - "resolveIntertwinedAssignedType\0" /* 6319 */ - "dimFetch\0" /* 6350 */ - "PhpParser\\Node\\Expr\\ArrayDimFetch\0" /* 6359 */ - "isDimFetchPathReachable\0" /* 6393 */ - "unsetExpression\0" /* 6417 */ - "getStateType\0" /* 6433 */ - "getScopeStateType\0" /* 6446 */ - "getScopeStateNativeType\0" /* 6464 */ - "resolveScopeStateType\0" /* 6488 */ - "specifyExpressionType\0" /* 6510 */ - "openSpecificationScope\0" /* 6532 */ - "isSpecifyExpressionTypeNoop\0" /* 6555 */ - "specifyExpressionTypeInPlace\0" /* 6583 */ - "assignExpression\0" /* 6612 */ - "fetchedOnType\0" /* 6629 */ - "assignInitializedProperty\0" /* 6643 */ - "expressionToInvalidate\0" /* 6669 */ - "requireMoreCharacters\0" /* 6692 */ - "invalidatingClass\0" /* 6714 */ - "keepPropertyFetches\0" /* 6732 */ - "invalidateExpression\0" /* 6752 */ - "isPrivatePropertyOfDifferentClass\0" /* 6773 */ - "invalidateMethodsOnExpression\0" /* 6807 */ - "setExpressionCertaintyKeepingType\0" /* 6837 */ - "isComplexUnionType\0" /* 6871 */ - "addTypeToExpression\0" /* 6890 */ - "typeToRemove\0" /* 6910 */ - "removeTypeFromExpression\0" /* 6923 */ - "filterByTruthyValue\0" /* 6948 */ - "filterByFalseyValue\0" /* 6968 */ - "specifiedTypes\0" /* 6988 */ - "applySpecifiedTypes\0" /* 7003 */ - "specifiedExpressions\0" /* 7023 */ - "processConditionalExpressionsAfterSpecifying\0" /* 7044 */ - "getConditionalExpressions\0" /* 7089 */ - "conditionalExpressionHolders\0" /* 7115 */ - "addConditionalExpressions\0" /* 7144 */ - "exitFirstLevelStatements\0" /* 7170 */ - "isInFirstLevelStatement\0" /* 7195 */ - "otherScope\0" /* 7219 */ - "preserveVacuousConditionals\0" /* 7230 */ - "mergeWith\0" /* 7258 */ - "ours\0" /* 7268 */ - "theirs\0" /* 7273 */ - "collectAbsorbedClosures\0" /* 7280 */ - "mergeWithVariableState\0" /* 7304 */ - "differingExpressionKeys\0" /* 7327 */ - "ourExpressionTypes\0" /* 7351 */ - "theirExpressionTypes\0" /* 7370 */ - "withoutPreciseClassConstantFetches\0" /* 7391 */ - "currentConditionalExpressions\0" /* 7426 */ - "sourceConditionalExpressions\0" /* 7456 */ - "otherExpressionTypes\0" /* 7485 */ - "preserveVacuousConditionalExpressions\0" /* 7506 */ - "ourConditionalExpressions\0" /* 7544 */ - "theirConditionalExpressions\0" /* 7570 */ - "mergeSameGuardConditionalExpressions\0" /* 7598 */ - "newConditionalExpressions\0" /* 7635 */ - "existingConditionalExpressions\0" /* 7661 */ - "mergeConditionalExpressions\0" /* 7692 */ - "calledMethodScope\0" /* 7720 */ - "mergeInitializedProperties\0" /* 7738 */ - "finallyScope\0" /* 7765 */ - "originalFinallyScope\0" /* 7778 */ - "processFinallyScope\0" /* 7799 */ - "ourVariableTypeHolders\0" /* 7819 */ - "finallyVariableTypeHolders\0" /* 7842 */ - "originalVariableTypeHolders\0" /* 7869 */ - "processFinallyScopeVariableTypeHolders\0" /* 7897 */ - "closureScope\0" /* 7936 */ - "prevScope\0" /* 7949 */ - "byRefUses\0" /* 7959 */ - "processClosureScope\0" /* 7969 */ - "finalScope\0" /* 7989 */ - "processAlwaysIterableForeachScopeWithoutPollute\0" /* 8000 */ - "writableVariableNames\0" /* 8048 */ - "generalizeWith\0" /* 8070 */ - "generalizeWithVariableState\0" /* 8085 */ - "variableTypeHolders\0" /* 8113 */ - "otherVariableTypeHolders\0" /* 8133 */ - "generalizeVariableTypeHolders\0" /* 8158 */ - "flattenUnionForGeneralization\0" /* 8188 */ - "a\0" /* 8218 */ - "b\0" /* 8220 */ - "depth\0" /* 8222 */ - "generalizeType\0" /* 8228 */ - "getArrayDepth\0" /* 8243 */ - "equals\0" /* 8257 */ - "otherConditionalExpressions\0" /* 8264 */ - "compareConditionalExpressions\0" /* 8292 */ - "compareVariableTypeHolders\0" /* 8322 */ - "propertyReflection\0" /* 8349 */ - "PHPStan\\Reflection\\PropertyReflection\0" /* 8368 */ - "canAccessProperty\0" /* 8406 */ - "PHPStan\\Reflection\\ExtendedPropertyReflection\0" /* 8424 */ - "canReadProperty\0" /* 8470 */ - "canWriteProperty\0" /* 8486 */ - "methodReflection\0" /* 8503 */ - "PHPStan\\Reflection\\MethodReflection\0" /* 8520 */ - "canCallMethod\0" /* 8556 */ - "constantReflection\0" /* 8570 */ - "PHPStan\\Reflection\\ClassConstantReflection\0" /* 8589 */ - "canAccessConstant\0" /* 8632 */ - "classMemberReflection\0" /* 8650 */ - "PHPStan\\Reflection\\ClassMemberReflection\0" /* 8672 */ - "canAccessClassMember\0" /* 8713 */ - "debug\0" /* 8734 */ - "typeWithMethod\0" /* 8740 */ - "methodName\0" /* 8755 */ - "filterTypeWithMethod\0" /* 8766 */ - "PHPStan\\Reflection\\ExtendedMethodReflection\0" /* 8787 */ - "getMethodReflection\0" /* 8831 */ - "getNakedMethod\0" /* 8851 */ - "typeWithProperty\0" /* 8866 */ - "getPropertyReflection\0" /* 8883 */ - "getInstancePropertyReflection\0" /* 8905 */ - "getStaticPropertyReflection\0" /* 8935 */ - "typeWithConstant\0" /* 8963 */ - "constantName\0" /* 8980 */ - "getConstantReflection\0" /* 8993 */ - "constantType\0" /* 9015 */ - "getConstantExplicitTypeFromConfig\0" /* 9028 */ - "getConstantTypes\0" /* 9062 */ - "getGlobalConstantType\0" /* 9079 */ - "nameString\0" /* 9101 */ - "createGlobalConstantFetches\0" /* 9112 */ - "getNativeConstantTypes\0" /* 9140 */ - "getIterableKeyType\0" /* 9163 */ - "getIterableValueType\0" /* 9182 */ - "PHPStan\\Php\\PhpVersions\0" /* 9203 */ - "getPhpVersion\0" /* 9227 */ - "isOverallPhpVersionRange\0" /* 9241 */ - "PhpParser\\Node\0" /* 9266 */ - "invokeNodeCallback\0" /* 9281 */ - "collectorType\0" /* 9300 */ - "data\0" /* 9314 */ - "emitCollectedData\0" /* 9319 */ - "extensionClass\0" /* 9337 */ - "trackValueDependency\0" /* 9352 */ - "file\0" /* 9373 */ - "trackFileDependency\0" /* 9378 */ - "directory\0" /* 9398 */ - "pattern\0" /* 9408 */ - "'*'\0" /* 9416 */ - "trackDirectoryDependency\0" /* 9420 */ - "trackClassDependency"; /* 9445 */ + "services\0" /* 0 */ + "PHPStan\\Analyser\\ScopeServices\0" /* 9 */ + "scopeFactory\0" /* 40 */ + "PHPStan\\Analyser\\InternalScopeFactory\0" /* 53 */ + "context\0" /* 91 */ + "PHPStan\\Analyser\\ScopeContext\0" /* 99 */ + "declareStrictTypes\0" /* 129 */ + "false\0" /* 148 */ + "function\0" /* 154 */ + "PHPStan\\Reflection\\Php\\PhpFunctionFromParserNodeReflection\0" /* 163 */ + "null\0" /* 222 */ + "namespace\0" /* 227 */ + "expressionTypes\0" /* 237 */ + "[]\0" /* 253 */ + "nativeExpressionTypes\0" /* 256 */ + "conditionalExpressions\0" /* 278 */ + "inClosureBindScopeClasses\0" /* 301 */ + "anonymousFunctionReflection\0" /* 327 */ + "PHPStan\\Type\\ClosureType\0" /* 355 */ + "inFirstLevelStatement\0" /* 380 */ + "true\0" /* 402 */ + "currentlyAssignedExpressions\0" /* 407 */ + "currentlyAllowedUndefinedExpressions\0" /* 436 */ + "inFunctionCallsStack\0" /* 473 */ + "afterExtractCall\0" /* 494 */ + "parentScope\0" /* 511 */ + "PHPStan\\Analyser\\MutatingScope\0" /* 523 */ + "nativeTypesPromoted\0" /* 554 */ + "templateArgumentFrame\0" /* 574 */ + "PHPStan\\Analyser\\Generics\\TemplateArgumentFrame\0" /* 596 */ + "templateArgumentConstraints\0" /* 644 */ + "PHPStan\\Analyser\\Generics\\TemplateArgumentConstraints\0" /* 672 */ + "__construct\0" /* 726 */ + "\0" /* 738 */ + "toNodeCallbackScope\0" /* 739 */ + "toWalkScope\0" /* 759 */ + "toMutatingScope\0" /* 771 */ + "getFile\0" /* 787 */ + "getFileDescription\0" /* 795 */ + "isDeclareStrictTypes\0" /* 814 */ + "enterDeclareStrictTypes\0" /* 835 */ + "currentExpressionTypes\0" /* 859 */ + "rememberConstructorExpressions\0" /* 882 */ + "classHasCustomSerialization\0" /* 913 */ + "rememberConstructorScope\0" /* 941 */ + "expr\0" /* 966 */ + "PhpParser\\Node\\Expr\\PropertyFetch\0" /* 971 */ + "allowOnlyOnThis\0" /* 1005 */ + "isReadonlyPropertyFetch\0" /* 1021 */ + "isInClass\0" /* 1045 */ + "isInTrait\0" /* 1055 */ + "PHPStan\\Reflection\\ClassReflection\0" /* 1065 */ + "getClassReflection\0" /* 1100 */ + "getTraitReflection\0" /* 1119 */ + "getFunction\0" /* 1138 */ + "getFunctionName\0" /* 1150 */ + "getNamespace\0" /* 1166 */ + "getParentScope\0" /* 1179 */ + "canAnyVariableExist\0" /* 1194 */ + "afterClearstatcacheCall\0" /* 1214 */ + "openSslFunctionName\0" /* 1238 */ + "afterOpenSslCall\0" /* 1258 */ + "invalidateVolatileExpressions\0" /* 1275 */ + "functionNames\0" /* 1305 */ + "declaredSymbolName\0" /* 1319 */ + "invalidateExistenceCheckExpressions\0" /* 1338 */ + "variableName\0" /* 1374 */ + "PHPStan\\TrinaryLogic\0" /* 1387 */ + "hasVariableType\0" /* 1408 */ + "PHPStan\\Type\\Type\0" /* 1424 */ + "getVariableType\0" /* 1442 */ + "getDefinedVariables\0" /* 1458 */ + "getMaybeDefinedVariables\0" /* 1478 */ + "PhpParser\\Node\\Expr\0" /* 1503 */ + "findPossiblyImpureCallDescriptions\0" /* 1523 */ + "isGlobalVariable\0" /* 1558 */ + "name\0" /* 1575 */ + "PhpParser\\Node\\Name\0" /* 1580 */ + "hasConstant\0" /* 1600 */ + "fileHasCompilerHaltStatementCalls\0" /* 1612 */ + "isInAnonymousFunction\0" /* 1646 */ + "getAnonymousFunctionReflection\0" /* 1668 */ + "getAnonymousFunctionReturnType\0" /* 1699 */ + "withAnonymousFunctionReflection\0" /* 1730 */ + "node\0" /* 1762 */ + "getType\0" /* 1767 */ + "getScopeType\0" /* 1775 */ + "getScopeNativeType\0" /* 1788 */ + "getNodeKey\0" /* 1807 */ + "PHPStan\\Node\\Printer\\ExprPrinter\0" /* 1818 */ + "getExprPrinter\0" /* 1851 */ + "duplicateWith\0" /* 1866 */ + "relevantRoots\0" /* 1880 */ + "getClosureScopeCacheKey\0" /* 1894 */ + "exprString\0" /* 1918 */ + "roots\0" /* 1929 */ + "exprStringIsRootedIn\0" /* 1935 */ + "resolveType\0" /* 1956 */ + "resolveTypeOfNewWorldHandlerNode\0" /* 1968 */ + "getCurrentTypesOfSpecifiedExpr\0" /* 2001 */ + "PHPStan\\Analyser\\TypeSpecifierContext\0" /* 2032 */ + "PHPStan\\Analyser\\SpecifiedTypes\0" /* 2070 */ + "specifyTypesOfNewWorldHandlerNode\0" /* 2102 */ + "PHPStan\\Analyser\\ExpressionResult\0" /* 2136 */ + "obtainResultForNode\0" /* 2170 */ + "storage\0" /* 2190 */ + "PHPStan\\Analyser\\ExpressionResultStorage\0" /* 2198 */ + "pushExpressionResultStorage\0" /* 2239 */ + "popExpressionResultStorage\0" /* 2267 */ + "findSettledStoredResult\0" /* 2294 */ + "getCurrentExpressionResultStorage\0" /* 2318 */ + "frame\0" /* 2352 */ + "withTemplateArgumentFrame\0" /* 2358 */ + "getCurrentTemplateArgumentFrame\0" /* 2384 */ + "getTemplateArgumentConstraints\0" /* 2416 */ + "constraints\0" /* 2447 */ + "withTemplateArgumentConstraints\0" /* 2459 */ + "addTemplateArgumentConstraints\0" /* 2491 */ + "withoutMemoizedTypes\0" /* 2522 */ + "other\0" /* 2543 */ + "getDifferingVariableRoots\0" /* 2549 */ + "key\0" /* 2575 */ + "getVariablesOfExpressionKey\0" /* 2579 */ + "recordedEntry\0" /* 2607 */ + "recordedExit\0" /* 2621 */ + "withRecordedStatementDelta\0" /* 2634 */ + "current\0" /* 2661 */ + "applyRecordedHolderDelta\0" /* 2669 */ + "getNativeType\0" /* 2694 */ + "getKeepVoidType\0" /* 2708 */ + "doNotTreatPhpDocTypesAsCertain\0" /* 2724 */ + "promoteNativeTypes\0" /* 2755 */ + "resolveName\0" /* 2774 */ + "PHPStan\\Type\\TypeWithClassName\0" /* 2786 */ + "resolveTypeByName\0" /* 2817 */ + "value\0" /* 2835 */ + "getTypeFromValue\0" /* 2841 */ + "hasExpressionType\0" /* 2858 */ + "getTrackedExpressionType\0" /* 2876 */ + "reflection\0" /* 2901 */ + "parameter\0" /* 2912 */ + "PHPStan\\Reflection\\ParameterReflection\0" /* 2922 */ + "rememberTypes\0" /* 2961 */ + "pushInFunctionCall\0" /* 2975 */ + "popInFunctionCall\0" /* 2994 */ + "className\0" /* 3012 */ + "isInClassExists\0" /* 3022 */ + "getFunctionCallStack\0" /* 3038 */ + "getFunctionCallStackWithParameters\0" /* 3059 */ + "functionName\0" /* 3094 */ + "isInFunctionExists\0" /* 3107 */ + "classReflection\0" /* 3126 */ + "enterClass\0" /* 3142 */ + "traitReflection\0" /* 3153 */ + "enterTrait\0" /* 3169 */ + "classMethod\0" /* 3180 */ + "PhpParser\\Node\\Stmt\\ClassMethod\0" /* 3192 */ + "templateTypeMap\0" /* 3224 */ + "PHPStan\\Type\\Generic\\TemplateTypeMap\0" /* 3240 */ + "phpDocParameterTypes\0" /* 3277 */ + "phpDocReturnType\0" /* 3298 */ + "throwType\0" /* 3315 */ + "deprecatedDescription\0" /* 3325 */ + "isDeprecated\0" /* 3347 */ + "isInternal\0" /* 3360 */ + "isFinal\0" /* 3371 */ + "isPure\0" /* 3379 */ + "acceptsNamedArguments\0" /* 3386 */ + "asserts\0" /* 3408 */ + "PHPStan\\Reflection\\Assertions\0" /* 3416 */ + "selfOutType\0" /* 3446 */ + "phpDocComment\0" /* 3458 */ + "parameterOutTypes\0" /* 3472 */ + "immediatelyInvokedCallableParameters\0" /* 3490 */ + "phpDocClosureThisTypeParameters\0" /* 3527 */ + "isConstructor\0" /* 3559 */ + "resolvedPhpDocBlock\0" /* 3573 */ + "PHPStan\\PhpDoc\\ResolvedPhpDocBlock\0" /* 3593 */ + "phpDocPureUnlessCallableIsImpureParameters\0" /* 3628 */ + "phpDocPureUnlessParameterPassedParameters\0" /* 3671 */ + "enterClassMethod\0" /* 3713 */ + "hook\0" /* 3730 */ + "PhpParser\\Node\\PropertyHook\0" /* 3735 */ + "propertyName\0" /* 3763 */ + "nativePropertyTypeNode\0" /* 3776 */ + "PhpParser\\Node\\Identifier|PhpParser\\Node\\Name|PhpParser\\Node\\ComplexType\0" /* 3799 */ + "phpDocPropertyType\0" /* 3872 */ + "enterPropertyHook\0" /* 3891 */ + "type\0" /* 3909 */ + "transformStaticType\0" /* 3914 */ + "functionLike\0" /* 3934 */ + "PhpParser\\Node\\FunctionLike\0" /* 3947 */ + "getRealParameterTypes\0" /* 3975 */ + "getRealParameterDefaultValues\0" /* 3997 */ + "PhpParser\\Node\\Stmt\\ClassMethod|PhpParser\\Node\\Stmt\\Function_|PhpParser\\Node\\PropertyHook\0" /* 4027 */ + "getParameterAttributes\0" /* 4117 */ + "PhpParser\\Node\\Stmt\\Function_\0" /* 4140 */ + "pureUnlessCallableIsImpureParameters\0" /* 4170 */ + "pureUnlessParameterPassedParameters\0" /* 4207 */ + "enterFunction\0" /* 4243 */ + "functionReflection\0" /* 4257 */ + "preserveConstructorScope\0" /* 4276 */ + "enterFunctionLike\0" /* 4301 */ + "namespaceName\0" /* 4319 */ + "enterNamespace\0" /* 4333 */ + "thisType\0" /* 4348 */ + "nativeThisType\0" /* 4357 */ + "scopeClasses\0" /* 4372 */ + "enterClosureBind\0" /* 4385 */ + "originalScope\0" /* 4402 */ + "restoreOriginalScopeAfterClosureBind\0" /* 4416 */ + "restoreThisScope\0" /* 4453 */ + "restoreThis\0" /* 4470 */ + "enterClosureCall\0" /* 4482 */ + "isInClosureBind\0" /* 4499 */ + "withClosureBindScopeClasses\0" /* 4515 */ + "closure\0" /* 4543 */ + "PhpParser\\Node\\Expr\\Closure\0" /* 4551 */ + "callableParameters\0" /* 4579 */ + "nativeCallableParameters\0" /* 4598 */ + "enterAnonymousFunction\0" /* 4623 */ + "enterAnonymousFunctionWithoutReflection\0" /* 4646 */ + "typeHolder\0" /* 4686 */ + "PHPStan\\Analyser\\ExpressionTypeHolder\0" /* 4697 */ + "expressionTypeIsUnchangeable\0" /* 4735 */ + "invalidateStaticExpressions\0" /* 4764 */ + "arrowFunction\0" /* 4792 */ + "PhpParser\\Node\\Expr\\ArrowFunction\0" /* 4806 */ + "enterArrowFunction\0" /* 4840 */ + "enterArrowFunctionWithoutReflection\0" /* 4859 */ + "PhpParser\\Node\\Param\0" /* 4895 */ + "isParameterValueNullable\0" /* 4916 */ + "isNullable\0" /* 4941 */ + "isVariadic\0" /* 4952 */ + "getFunctionType\0" /* 4963 */ + "index\0" /* 4979 */ + "getCallableParameterType\0" /* 4985 */ + "startIndex\0" /* 5010 */ + "buildVariadicArrayTypeFromCallableParameters\0" /* 5021 */ + "nativeType\0" /* 5066 */ + "inferredType\0" /* 5077 */ + "intersectButNotNever\0" /* 5090 */ + "PhpParser\\Node\\Expr\\Match_\0" /* 5111 */ + "condType\0" /* 5138 */ + "condNativeType\0" /* 5147 */ + "enterMatch\0" /* 5162 */ + "iteratee\0" /* 5173 */ + "iterateeType\0" /* 5182 */ + "nativeIterateeType\0" /* 5195 */ + "valueName\0" /* 5214 */ + "keyName\0" /* 5224 */ + "valueByRef\0" /* 5232 */ + "enterForeach\0" /* 5243 */ + "enterForeachKey\0" /* 5256 */ + "catchType\0" /* 5272 */ + "enterCatchType\0" /* 5282 */ + "isPlainWrite\0" /* 5297 */ + "enterExpressionAssign\0" /* 5310 */ + "exitExpressionAssign\0" /* 5332 */ + "isInExpressionAssign\0" /* 5353 */ + "isInWriteExpressionAssign\0" /* 5374 */ + "setAllowedUndefinedExpression\0" /* 5400 */ + "unsetAllowedUndefinedExpression\0" /* 5430 */ + "isUndefinedExpressionAllowed\0" /* 5462 */ + "certainty\0" /* 5491 */ + "intertwinedPropagatedFrom\0" /* 5501 */ + "assignVariable\0" /* 5527 */ + "overwriteExpression\0" /* 5542 */ + "scope\0" /* 5562 */ + "rootType\0" /* 5568 */ + "assignedExpr\0" /* 5577 */ + "rootVariableName\0" /* 5590 */ + "native\0" /* 5607 */ + "resolveIntertwinedAssignedType\0" /* 5614 */ + "dimFetch\0" /* 5645 */ + "PhpParser\\Node\\Expr\\ArrayDimFetch\0" /* 5654 */ + "isDimFetchPathReachable\0" /* 5688 */ + "unsetExpression\0" /* 5712 */ + "getStateType\0" /* 5728 */ + "getScopeStateType\0" /* 5741 */ + "getScopeStateNativeType\0" /* 5759 */ + "resolveScopeStateType\0" /* 5783 */ + "specifyExpressionType\0" /* 5805 */ + "openSpecificationScope\0" /* 5827 */ + "isSpecifyExpressionTypeNoop\0" /* 5850 */ + "specifyExpressionTypeInPlace\0" /* 5878 */ + "assignExpression\0" /* 5907 */ + "fetchedOnType\0" /* 5924 */ + "assignInitializedProperty\0" /* 5938 */ + "expressionToInvalidate\0" /* 5964 */ + "requireMoreCharacters\0" /* 5987 */ + "invalidatingClass\0" /* 6009 */ + "keepPropertyFetches\0" /* 6027 */ + "invalidateExpression\0" /* 6047 */ + "isPrivatePropertyOfDifferentClass\0" /* 6068 */ + "invalidateMethodsOnExpression\0" /* 6102 */ + "setExpressionCertaintyKeepingType\0" /* 6132 */ + "isComplexUnionType\0" /* 6166 */ + "addTypeToExpression\0" /* 6185 */ + "typeToRemove\0" /* 6205 */ + "removeTypeFromExpression\0" /* 6218 */ + "filterByTruthyValue\0" /* 6243 */ + "filterByFalseyValue\0" /* 6263 */ + "specifiedTypes\0" /* 6283 */ + "applySpecifiedTypes\0" /* 6298 */ + "specifiedExpressions\0" /* 6318 */ + "processConditionalExpressionsAfterSpecifying\0" /* 6339 */ + "getConditionalExpressions\0" /* 6384 */ + "conditionalExpressionHolders\0" /* 6410 */ + "addConditionalExpressions\0" /* 6439 */ + "exitFirstLevelStatements\0" /* 6465 */ + "isInFirstLevelStatement\0" /* 6490 */ + "otherScope\0" /* 6514 */ + "preserveVacuousConditionals\0" /* 6525 */ + "mergeWith\0" /* 6553 */ + "ours\0" /* 6563 */ + "theirs\0" /* 6568 */ + "collectAbsorbedClosures\0" /* 6575 */ + "mergeWithVariableState\0" /* 6599 */ + "differingExpressionKeys\0" /* 6622 */ + "ourExpressionTypes\0" /* 6646 */ + "theirExpressionTypes\0" /* 6665 */ + "withoutPreciseClassConstantFetches\0" /* 6686 */ + "currentConditionalExpressions\0" /* 6721 */ + "sourceConditionalExpressions\0" /* 6751 */ + "otherExpressionTypes\0" /* 6780 */ + "preserveVacuousConditionalExpressions\0" /* 6801 */ + "ourConditionalExpressions\0" /* 6839 */ + "theirConditionalExpressions\0" /* 6865 */ + "mergeSameGuardConditionalExpressions\0" /* 6893 */ + "newConditionalExpressions\0" /* 6930 */ + "existingConditionalExpressions\0" /* 6956 */ + "mergeConditionalExpressions\0" /* 6987 */ + "calledMethodScope\0" /* 7015 */ + "mergeInitializedProperties\0" /* 7033 */ + "finallyScope\0" /* 7060 */ + "originalFinallyScope\0" /* 7073 */ + "processFinallyScope\0" /* 7094 */ + "ourVariableTypeHolders\0" /* 7114 */ + "finallyVariableTypeHolders\0" /* 7137 */ + "originalVariableTypeHolders\0" /* 7164 */ + "processFinallyScopeVariableTypeHolders\0" /* 7192 */ + "closureScope\0" /* 7231 */ + "prevScope\0" /* 7244 */ + "byRefUses\0" /* 7254 */ + "processClosureScope\0" /* 7264 */ + "finalScope\0" /* 7284 */ + "processAlwaysIterableForeachScopeWithoutPollute\0" /* 7295 */ + "writableVariableNames\0" /* 7343 */ + "generalizeWith\0" /* 7365 */ + "generalizeWithVariableState\0" /* 7380 */ + "variableTypeHolders\0" /* 7408 */ + "otherVariableTypeHolders\0" /* 7428 */ + "generalizeVariableTypeHolders\0" /* 7453 */ + "flattenUnionForGeneralization\0" /* 7483 */ + "a\0" /* 7513 */ + "b\0" /* 7515 */ + "depth\0" /* 7517 */ + "generalizeType\0" /* 7523 */ + "getArrayDepth\0" /* 7538 */ + "equals\0" /* 7552 */ + "otherConditionalExpressions\0" /* 7559 */ + "compareConditionalExpressions\0" /* 7587 */ + "compareVariableTypeHolders\0" /* 7617 */ + "propertyReflection\0" /* 7644 */ + "PHPStan\\Reflection\\PropertyReflection\0" /* 7663 */ + "canAccessProperty\0" /* 7701 */ + "PHPStan\\Reflection\\ExtendedPropertyReflection\0" /* 7719 */ + "canReadProperty\0" /* 7765 */ + "canWriteProperty\0" /* 7781 */ + "methodReflection\0" /* 7798 */ + "PHPStan\\Reflection\\MethodReflection\0" /* 7815 */ + "canCallMethod\0" /* 7851 */ + "constantReflection\0" /* 7865 */ + "PHPStan\\Reflection\\ClassConstantReflection\0" /* 7884 */ + "canAccessConstant\0" /* 7927 */ + "classMemberReflection\0" /* 7945 */ + "PHPStan\\Reflection\\ClassMemberReflection\0" /* 7967 */ + "canAccessClassMember\0" /* 8008 */ + "debug\0" /* 8029 */ + "typeWithMethod\0" /* 8035 */ + "methodName\0" /* 8050 */ + "filterTypeWithMethod\0" /* 8061 */ + "PHPStan\\Reflection\\ExtendedMethodReflection\0" /* 8082 */ + "getMethodReflection\0" /* 8126 */ + "getNakedMethod\0" /* 8146 */ + "typeWithProperty\0" /* 8161 */ + "getPropertyReflection\0" /* 8178 */ + "getInstancePropertyReflection\0" /* 8200 */ + "getStaticPropertyReflection\0" /* 8230 */ + "typeWithConstant\0" /* 8258 */ + "constantName\0" /* 8275 */ + "getConstantReflection\0" /* 8288 */ + "constantType\0" /* 8310 */ + "getConstantExplicitTypeFromConfig\0" /* 8323 */ + "getConstantTypes\0" /* 8357 */ + "getGlobalConstantType\0" /* 8374 */ + "nameString\0" /* 8396 */ + "createGlobalConstantFetches\0" /* 8407 */ + "getNativeConstantTypes\0" /* 8435 */ + "getIterableKeyType\0" /* 8458 */ + "getIterableValueType\0" /* 8477 */ + "PHPStan\\Php\\PhpVersions\0" /* 8498 */ + "getPhpVersion\0" /* 8522 */ + "isOverallPhpVersionRange\0" /* 8536 */ + "PhpParser\\Node\0" /* 8561 */ + "invokeNodeCallback\0" /* 8576 */ + "collectorType\0" /* 8595 */ + "data\0" /* 8609 */ + "emitCollectedData\0" /* 8614 */ + "extensionClass\0" /* 8632 */ + "trackValueDependency\0" /* 8647 */ + "file\0" /* 8668 */ + "trackFileDependency\0" /* 8673 */ + "directory\0" /* 8693 */ + "pattern\0" /* 8703 */ + "'*'\0" /* 8711 */ + "trackDirectoryDependency\0" /* 8715 */ + "trackClassDependency"; /* 8740 */ inline constexpr reg::PackedArg args[] = { - reg::packed(0, 0, 10), /* __construct $container */ - reg::packed(48, 0, 61), /* __construct $scopeFactory */ - reg::packed(99, 0, 118), /* __construct $reflectionProvider */ - reg::packed(156, 0, 184), /* __construct $initializerExprTypeResolver */ - reg::packed(231, 0, 264), /* __construct $expressionTypeResolverExtensions */ - reg::packed(313, 0, 325), /* __construct $exprPrinter */ - reg::packed(358, 0, 372), /* __construct $typeSpecifier */ - reg::packed(403, 0, 428), /* __construct $propertyReflectionFinder */ - reg::packed(478, 0, 485), /* __construct $parser */ - reg::packed(507, 0, 524), /* __construct $constantResolver */ - reg::packed(558, 0, 587), /* __construct $expressionResultStorageStack */ - reg::packed(633, 0, 641), /* __construct $context */ - reg::packed(671, 0, 682), /* __construct $phpVersion */ - reg::packed(705, 0, 732), /* __construct $attributeReflectionFactory */ - reg::packed(778, 0, 810), /* __construct $configuredPhpVersionRangeHelper */ - reg::packed(854, 0, reg::NoString, false, false, 867), /* __construct $nodeCallback */ - reg::packed(872, MAY_BE_BOOL, reg::NoString, false, false, 891), /* __construct $declareStrictTypes */ - reg::packed(897, MAY_BE_NULL, 906, false, false, 867), /* __construct $function */ - reg::packed(965, MAY_BE_NULL | MAY_BE_STRING, reg::NoString, false, false, 867), /* __construct $namespace */ - reg::packed(975, MAY_BE_ARRAY, reg::NoString, false, false, 991), /* __construct $expressionTypes */ - reg::packed(994, MAY_BE_ARRAY, reg::NoString, false, false, 991), /* __construct $nativeExpressionTypes */ - reg::packed(1016, MAY_BE_ARRAY, reg::NoString, false, false, 991), /* __construct $conditionalExpressions */ - reg::packed(1039, MAY_BE_ARRAY, reg::NoString, false, false, 991), /* __construct $inClosureBindScopeClasses */ - reg::packed(1065, MAY_BE_NULL, 1093, false, false, 867), /* __construct $anonymousFunctionReflection */ - reg::packed(1118, MAY_BE_BOOL, reg::NoString, false, false, 1140), /* __construct $inFirstLevelStatement */ - reg::packed(1145, MAY_BE_ARRAY, reg::NoString, false, false, 991), /* __construct $currentlyAssignedExpressions */ - reg::packed(1174, MAY_BE_ARRAY, reg::NoString, false, false, 991), /* __construct $currentlyAllowedUndefinedExpressions */ - reg::packed(1211, MAY_BE_ARRAY, reg::NoString, false, false, 991), /* __construct $inFunctionCallsStack */ - reg::packed(1232, MAY_BE_BOOL, reg::NoString, false, false, 891), /* __construct $afterExtractCall */ - reg::packed(1249, MAY_BE_NULL, 1261, false, false, 867), /* __construct $parentScope */ - reg::packed(1292, MAY_BE_BOOL, reg::NoString, false, false, 891), /* __construct $nativeTypesPromoted */ - reg::packed(1312, MAY_BE_NULL, 1334, false, false, 867), /* __construct $templateArgumentFrame */ - reg::packed(1382, MAY_BE_NULL, 1410, false, false, 867), /* __construct $templateArgumentConstraints */ - reg::packed(1476, 0, 1261), /* toNodeCallbackScope return */ - reg::packed(1476, 0, 1261), /* toWalkScope return */ - reg::packed(1476, 0, 1261), /* toMutatingScope return */ - reg::packed(1476, MAY_BE_STRING), /* getFile return */ - reg::packed(1476, MAY_BE_STRING), /* getFileDescription return */ - reg::packed(1476, MAY_BE_BOOL), /* isDeclareStrictTypes return */ - reg::packed(1476, 0, 1261), /* enterDeclareStrictTypes return */ - reg::packed(1597, MAY_BE_ARRAY), /* rememberConstructorExpressions $currentExpressionTypes */ - reg::packed(1476, MAY_BE_ARRAY), /* rememberConstructorExpressions return */ - reg::packed(1476, MAY_BE_BOOL), /* classHasCustomSerialization return */ - reg::packed(1476, 0, 1261), /* rememberConstructorScope return */ - reg::packed(1704, 0, 1709), /* isReadonlyPropertyFetch $expr */ - reg::packed(1743, MAY_BE_BOOL), /* isReadonlyPropertyFetch $allowOnlyOnThis */ - reg::packed(1476, MAY_BE_BOOL), /* isReadonlyPropertyFetch return */ - reg::packed(1476, MAY_BE_BOOL), /* isInClass return */ - reg::packed(1476, MAY_BE_BOOL), /* isInTrait return */ - reg::packed(1476, MAY_BE_NULL, 1803), /* getClassReflection return */ - reg::packed(1476, MAY_BE_NULL, 1803), /* getTraitReflection return */ - reg::packed(1476, MAY_BE_NULL, 906), /* getFunction return */ - reg::packed(1476, MAY_BE_NULL | MAY_BE_STRING), /* getFunctionName return */ - reg::packed(1476, MAY_BE_NULL | MAY_BE_STRING), /* getNamespace return */ - reg::packed(1476, MAY_BE_NULL, 1261), /* getParentScope return */ - reg::packed(1476, MAY_BE_BOOL), /* canAnyVariableExist return */ - reg::packed(1476, 0, 1261), /* afterExtractCall return */ - reg::packed(1476, 0, 1261), /* afterClearstatcacheCall return */ - reg::packed(1976, MAY_BE_STRING), /* afterOpenSslCall $openSslFunctionName */ - reg::packed(1476, 0, 1261), /* afterOpenSslCall return */ - reg::packed(1476, 0, 1261), /* invalidateVolatileExpressions return */ - reg::packed(2043, MAY_BE_ARRAY), /* invalidateExistenceCheckExpressions $functionNames */ - reg::packed(2057, MAY_BE_NULL | MAY_BE_STRING), /* invalidateExistenceCheckExpressions $declaredSymbolName */ - reg::packed(1476, 0, 1261), /* invalidateExistenceCheckExpressions return */ - reg::packed(2112, MAY_BE_STRING), /* hasVariableType $variableName */ - reg::packed(1476, 0, 2125), /* hasVariableType return */ - reg::packed(2112, MAY_BE_STRING), /* getVariableType $variableName */ - reg::packed(1476, 0, 2162), /* getVariableType return */ - reg::packed(1476, MAY_BE_ARRAY), /* getDefinedVariables return */ - reg::packed(1476, MAY_BE_ARRAY), /* getMaybeDefinedVariables return */ - reg::packed(1704, 0, 2241), /* findPossiblyImpureCallDescriptions $expr */ - reg::packed(1476, MAY_BE_ARRAY), /* findPossiblyImpureCallDescriptions return */ - reg::packed(2112, MAY_BE_STRING), /* isGlobalVariable $variableName */ - reg::packed(1476, MAY_BE_BOOL), /* isGlobalVariable return */ - reg::packed(2313, 0, 2318), /* hasConstant $name */ - reg::packed(1476, MAY_BE_BOOL), /* hasConstant return */ - reg::packed(1476, MAY_BE_BOOL), /* fileHasCompilerHaltStatementCalls return */ - reg::packed(1476, MAY_BE_BOOL), /* isInAnonymousFunction return */ - reg::packed(1476, MAY_BE_NULL, 1093), /* getAnonymousFunctionReflection return */ - reg::packed(1476, MAY_BE_NULL, 2162), /* getAnonymousFunctionReturnType return */ - reg::packed(1065, 0, 1093), /* withAnonymousFunctionReflection $anonymousFunctionReflection */ - reg::packed(1476, 0, 1261), /* withAnonymousFunctionReflection return */ - reg::packed(2500, 0, 2241), /* getType $node */ - reg::packed(1476, 0, 2162), /* getType return */ - reg::packed(1704, 0, 2241), /* getScopeType $expr */ - reg::packed(1476, 0, 2162), /* getScopeType return */ - reg::packed(1704, 0, 2241), /* getScopeNativeType $expr */ - reg::packed(1476, 0, 2162), /* getScopeNativeType return */ - reg::packed(2500, 0, 2241), /* getNodeKey $node */ - reg::packed(1476, MAY_BE_STRING), /* getNodeKey return */ - reg::packed(1476, 0, 325), /* getExprPrinter return */ - reg::packed(975, MAY_BE_ARRAY), /* duplicateWith $expressionTypes */ - reg::packed(994, MAY_BE_ARRAY), /* duplicateWith $nativeExpressionTypes */ - reg::packed(1016, MAY_BE_ARRAY), /* duplicateWith $conditionalExpressions */ - reg::packed(1145, MAY_BE_ARRAY), /* duplicateWith $currentlyAssignedExpressions */ - reg::packed(1174, MAY_BE_ARRAY), /* duplicateWith $currentlyAllowedUndefinedExpressions */ - reg::packed(1211, MAY_BE_ARRAY), /* duplicateWith $inFunctionCallsStack */ - reg::packed(1118, MAY_BE_BOOL), /* duplicateWith $inFirstLevelStatement */ - reg::packed(1232, MAY_BE_BOOL), /* duplicateWith $afterExtractCall */ - reg::packed(1476, 0, 1261), /* duplicateWith return */ - reg::packed(2585, MAY_BE_NULL | MAY_BE_ARRAY, reg::NoString, false, false, 867), /* getClosureScopeCacheKey $relevantRoots */ - reg::packed(1476, MAY_BE_STRING), /* getClosureScopeCacheKey return */ - reg::packed(2623, MAY_BE_STRING), /* exprStringIsRootedIn $exprString */ - reg::packed(2634, MAY_BE_ARRAY), /* exprStringIsRootedIn $roots */ - reg::packed(1476, MAY_BE_BOOL), /* exprStringIsRootedIn return */ - reg::packed(2623, MAY_BE_STRING), /* resolveType $exprString */ - reg::packed(2500, 0, 2241), /* resolveType $node */ - reg::packed(1476, 0, 2162), /* resolveType return */ - reg::packed(2500, 0, 2241), /* resolveTypeOfNewWorldHandlerNode $node */ - reg::packed(1476, 0, 2162), /* resolveTypeOfNewWorldHandlerNode return */ - reg::packed(1704, 0, 2241), /* getCurrentTypesOfSpecifiedExpr $expr */ - reg::packed(1476, MAY_BE_NULL | MAY_BE_ARRAY), /* getCurrentTypesOfSpecifiedExpr return */ - reg::packed(2500, 0, 2241), /* specifyTypesOfNewWorldHandlerNode $node */ - reg::packed(633, 0, 2737), /* specifyTypesOfNewWorldHandlerNode $context */ - reg::packed(1476, 0, 2775), /* specifyTypesOfNewWorldHandlerNode return */ - reg::packed(2500, 0, 2241), /* obtainResultForNode $node */ - reg::packed(1476, 0, 2841), /* obtainResultForNode return */ - reg::packed(2895, 0, 2903), /* pushExpressionResultStorage $storage */ - reg::packed(1476, MAY_BE_VOID), /* pushExpressionResultStorage return */ - reg::packed(1476, MAY_BE_VOID), /* popExpressionResultStorage return */ - reg::packed(2500, 0, 2241), /* findSettledStoredResult $node */ - reg::packed(1476, MAY_BE_NULL, 2841), /* findSettledStoredResult return */ - reg::packed(1476, MAY_BE_NULL, 2903), /* getCurrentExpressionResultStorage return */ - reg::packed(3057, MAY_BE_NULL, 1334), /* withTemplateArgumentFrame $frame */ - reg::packed(1476, 0, 1261), /* withTemplateArgumentFrame return */ - reg::packed(1476, MAY_BE_NULL, 1334), /* getCurrentTemplateArgumentFrame return */ - reg::packed(1476, MAY_BE_NULL, 1410), /* getTemplateArgumentConstraints return */ - reg::packed(3152, MAY_BE_NULL, 1410), /* withTemplateArgumentConstraints $constraints */ - reg::packed(1476, 0, 1261), /* withTemplateArgumentConstraints return */ - reg::packed(3152, MAY_BE_NULL, 1410), /* addTemplateArgumentConstraints $constraints */ - reg::packed(1476, 0, 1261), /* addTemplateArgumentConstraints return */ - reg::packed(1476, 0, 1261), /* withoutMemoizedTypes return */ - reg::packed(3248, 0, 1261), /* getDifferingVariableRoots $other */ - reg::packed(1476, MAY_BE_NULL | MAY_BE_ARRAY), /* getDifferingVariableRoots return */ - reg::packed(3280, MAY_BE_STRING), /* getVariablesOfExpressionKey $key */ - reg::packed(1476, MAY_BE_NULL | MAY_BE_ARRAY), /* getVariablesOfExpressionKey return */ - reg::packed(3312, 0, 1261), /* withRecordedStatementDelta $recordedEntry */ - reg::packed(3326, 0, 1261), /* withRecordedStatementDelta $recordedExit */ - reg::packed(1476, 0, 1261), /* withRecordedStatementDelta return */ - reg::packed(3366, MAY_BE_ARRAY), /* applyRecordedHolderDelta $current */ - reg::packed(3312, MAY_BE_ARRAY), /* applyRecordedHolderDelta $recordedEntry */ - reg::packed(3326, MAY_BE_ARRAY), /* applyRecordedHolderDelta $recordedExit */ - reg::packed(1476, MAY_BE_ARRAY), /* applyRecordedHolderDelta return */ - reg::packed(1704, 0, 2241), /* getNativeType $expr */ - reg::packed(1476, 0, 2162), /* getNativeType return */ - reg::packed(2500, 0, 2241), /* getKeepVoidType $node */ - reg::packed(1476, 0, 2162), /* getKeepVoidType return */ - reg::packed(1476, 0, 1261), /* doNotTreatPhpDocTypesAsCertain return */ - reg::packed(1476, 0, 1261), /* promoteNativeTypes return */ - reg::packed(2313, 0, 2318), /* resolveName $name */ - reg::packed(1476, MAY_BE_STRING), /* resolveName return */ - reg::packed(2313, 0, 2318), /* resolveTypeByName $name */ - reg::packed(1476, 0, 3491), /* resolveTypeByName return */ - reg::packed(3540, 0), /* getTypeFromValue $value */ - reg::packed(1476, 0, 2162), /* getTypeFromValue return */ - reg::packed(2500, 0, 2241), /* hasExpressionType $node */ - reg::packed(1476, 0, 2125), /* hasExpressionType return */ - reg::packed(2500, 0, 2241), /* getTrackedExpressionType $node */ - reg::packed(1476, 0, 2162), /* getTrackedExpressionType return */ - reg::packed(3606, 0), /* pushInFunctionCall $reflection */ - reg::packed(3617, MAY_BE_NULL, 3627), /* pushInFunctionCall $parameter */ - reg::packed(3666, MAY_BE_BOOL), /* pushInFunctionCall $rememberTypes */ - reg::packed(1476, 0, 1261), /* pushInFunctionCall return */ - reg::packed(1476, 0, 1261), /* popInFunctionCall return */ - reg::packed(3717, MAY_BE_STRING), /* isInClassExists $className */ - reg::packed(1476, MAY_BE_BOOL), /* isInClassExists return */ - reg::packed(1476, MAY_BE_ARRAY), /* getFunctionCallStack return */ - reg::packed(1476, MAY_BE_ARRAY), /* getFunctionCallStackWithParameters return */ - reg::packed(3799, MAY_BE_STRING), /* isInFunctionExists $functionName */ - reg::packed(1476, MAY_BE_BOOL), /* isInFunctionExists return */ - reg::packed(3831, 0, 1803), /* enterClass $classReflection */ - reg::packed(1476, 0, 1261), /* enterClass return */ - reg::packed(3858, 0, 1803), /* enterTrait $traitReflection */ - reg::packed(1476, 0, 1261), /* enterTrait return */ - reg::packed(3885, 0, 3897), /* enterClassMethod $classMethod */ - reg::packed(3929, 0, 3945), /* enterClassMethod $templateTypeMap */ - reg::packed(3982, MAY_BE_ARRAY), /* enterClassMethod $phpDocParameterTypes */ - reg::packed(4003, MAY_BE_NULL, 2162), /* enterClassMethod $phpDocReturnType */ - reg::packed(4020, MAY_BE_NULL, 2162), /* enterClassMethod $throwType */ - reg::packed(4030, MAY_BE_NULL | MAY_BE_STRING), /* enterClassMethod $deprecatedDescription */ - reg::packed(4052, MAY_BE_BOOL), /* enterClassMethod $isDeprecated */ - reg::packed(4065, MAY_BE_BOOL), /* enterClassMethod $isInternal */ - reg::packed(4076, MAY_BE_BOOL), /* enterClassMethod $isFinal */ - reg::packed(4084, MAY_BE_NULL | MAY_BE_BOOL, reg::NoString, false, false, 867), /* enterClassMethod $isPure */ - reg::packed(4091, MAY_BE_BOOL, reg::NoString, false, false, 1140), /* enterClassMethod $acceptsNamedArguments */ - reg::packed(4113, MAY_BE_NULL, 4121, false, false, 867), /* enterClassMethod $asserts */ - reg::packed(4151, MAY_BE_NULL, 2162, false, false, 867), /* enterClassMethod $selfOutType */ - reg::packed(4163, MAY_BE_NULL | MAY_BE_STRING, reg::NoString, false, false, 867), /* enterClassMethod $phpDocComment */ - reg::packed(4177, MAY_BE_ARRAY, reg::NoString, false, false, 991), /* enterClassMethod $parameterOutTypes */ - reg::packed(4195, MAY_BE_ARRAY, reg::NoString, false, false, 991), /* enterClassMethod $immediatelyInvokedCallableParameters */ - reg::packed(4232, MAY_BE_ARRAY, reg::NoString, false, false, 991), /* enterClassMethod $phpDocClosureThisTypeParameters */ - reg::packed(4264, MAY_BE_BOOL, reg::NoString, false, false, 891), /* enterClassMethod $isConstructor */ - reg::packed(4278, MAY_BE_NULL, 4298, false, false, 867), /* enterClassMethod $resolvedPhpDocBlock */ - reg::packed(4333, MAY_BE_ARRAY, reg::NoString, false, false, 991), /* enterClassMethod $phpDocPureUnlessCallableIsImpureParameters */ - reg::packed(4376, MAY_BE_ARRAY, reg::NoString, false, false, 991), /* enterClassMethod $phpDocPureUnlessParameterPassedParameters */ - reg::packed(1476, 0, 1261), /* enterClassMethod return */ - reg::packed(4435, 0, 4440), /* enterPropertyHook $hook */ - reg::packed(4468, MAY_BE_STRING), /* enterPropertyHook $propertyName */ - reg::packed(4481, MAY_BE_NULL, 4504), /* enterPropertyHook $nativePropertyTypeNode */ - reg::packed(4577, MAY_BE_NULL, 2162), /* enterPropertyHook $phpDocPropertyType */ - reg::packed(3982, MAY_BE_ARRAY), /* enterPropertyHook $phpDocParameterTypes */ - reg::packed(4020, MAY_BE_NULL, 2162), /* enterPropertyHook $throwType */ - reg::packed(4030, MAY_BE_NULL | MAY_BE_STRING), /* enterPropertyHook $deprecatedDescription */ - reg::packed(4052, MAY_BE_BOOL), /* enterPropertyHook $isDeprecated */ - reg::packed(4084, MAY_BE_NULL | MAY_BE_BOOL), /* enterPropertyHook $isPure */ - reg::packed(4163, MAY_BE_NULL | MAY_BE_STRING), /* enterPropertyHook $phpDocComment */ - reg::packed(4278, MAY_BE_NULL, 4298, false, false, 867), /* enterPropertyHook $resolvedPhpDocBlock */ - reg::packed(1476, 0, 1261), /* enterPropertyHook return */ - reg::packed(4614, 0, 2162), /* transformStaticType $type */ - reg::packed(1476, 0, 2162), /* transformStaticType return */ - reg::packed(4639, 0, 4652), /* getRealParameterTypes $functionLike */ - reg::packed(1476, MAY_BE_ARRAY), /* getRealParameterTypes return */ - reg::packed(4639, 0, 4652), /* getRealParameterDefaultValues $functionLike */ - reg::packed(1476, MAY_BE_ARRAY), /* getRealParameterDefaultValues return */ - reg::packed(4639, 0, 4732), /* getParameterAttributes $functionLike */ - reg::packed(1476, MAY_BE_ARRAY), /* getParameterAttributes return */ - reg::packed(897, 0, 4845), /* enterFunction $function */ - reg::packed(3929, 0, 3945), /* enterFunction $templateTypeMap */ - reg::packed(3982, MAY_BE_ARRAY), /* enterFunction $phpDocParameterTypes */ - reg::packed(4003, MAY_BE_NULL, 2162), /* enterFunction $phpDocReturnType */ - reg::packed(4020, MAY_BE_NULL, 2162), /* enterFunction $throwType */ - reg::packed(4030, MAY_BE_NULL | MAY_BE_STRING), /* enterFunction $deprecatedDescription */ - reg::packed(4052, MAY_BE_BOOL), /* enterFunction $isDeprecated */ - reg::packed(4065, MAY_BE_BOOL), /* enterFunction $isInternal */ - reg::packed(4084, MAY_BE_NULL | MAY_BE_BOOL, reg::NoString, false, false, 867), /* enterFunction $isPure */ - reg::packed(4091, MAY_BE_BOOL, reg::NoString, false, false, 1140), /* enterFunction $acceptsNamedArguments */ - reg::packed(4113, MAY_BE_NULL, 4121, false, false, 867), /* enterFunction $asserts */ - reg::packed(4163, MAY_BE_NULL | MAY_BE_STRING, reg::NoString, false, false, 867), /* enterFunction $phpDocComment */ - reg::packed(4177, MAY_BE_ARRAY, reg::NoString, false, false, 991), /* enterFunction $parameterOutTypes */ - reg::packed(4195, MAY_BE_ARRAY, reg::NoString, false, false, 991), /* enterFunction $immediatelyInvokedCallableParameters */ - reg::packed(4232, MAY_BE_ARRAY, reg::NoString, false, false, 991), /* enterFunction $phpDocClosureThisTypeParameters */ - reg::packed(4875, MAY_BE_ARRAY, reg::NoString, false, false, 991), /* enterFunction $pureUnlessCallableIsImpureParameters */ - reg::packed(4912, MAY_BE_ARRAY, reg::NoString, false, false, 991), /* enterFunction $pureUnlessParameterPassedParameters */ - reg::packed(1476, 0, 1261), /* enterFunction return */ - reg::packed(4962, 0, 906), /* enterFunctionLike $functionReflection */ - reg::packed(4981, MAY_BE_BOOL), /* enterFunctionLike $preserveConstructorScope */ - reg::packed(1476, 0, 1261), /* enterFunctionLike return */ - reg::packed(5024, MAY_BE_STRING), /* enterNamespace $namespaceName */ - reg::packed(1476, 0, 1261), /* enterNamespace return */ - reg::packed(5053, MAY_BE_NULL, 2162), /* enterClosureBind $thisType */ - reg::packed(5062, MAY_BE_NULL, 2162), /* enterClosureBind $nativeThisType */ - reg::packed(5077, MAY_BE_ARRAY), /* enterClosureBind $scopeClasses */ - reg::packed(1476, 0, 1261), /* enterClosureBind return */ - reg::packed(5107, 0, 1261), /* restoreOriginalScopeAfterClosureBind $originalScope */ - reg::packed(1476, 0, 1261), /* restoreOriginalScopeAfterClosureBind return */ - reg::packed(5158, 0, 1261), /* restoreThis $restoreThisScope */ - reg::packed(1476, 0, 1261), /* restoreThis return */ - reg::packed(5053, 0, 2162), /* enterClosureCall $thisType */ - reg::packed(5062, 0, 2162), /* enterClosureCall $nativeThisType */ - reg::packed(1476, 0, 1261), /* enterClosureCall return */ - reg::packed(1476, MAY_BE_BOOL), /* isInClosureBind return */ - reg::packed(5077, MAY_BE_ARRAY), /* withClosureBindScopeClasses $scopeClasses */ - reg::packed(1476, 0, 1261), /* withClosureBindScopeClasses return */ - reg::packed(5248, 0, 5256), /* enterAnonymousFunction $closure */ - reg::packed(5284, MAY_BE_NULL | MAY_BE_ARRAY), /* enterAnonymousFunction $callableParameters */ - reg::packed(5303, MAY_BE_NULL | MAY_BE_ARRAY, reg::NoString, false, false, 867), /* enterAnonymousFunction $nativeCallableParameters */ - reg::packed(1476, 0, 1261), /* enterAnonymousFunction return */ - reg::packed(5248, 0, 5256), /* enterAnonymousFunctionWithoutReflection $closure */ - reg::packed(5284, MAY_BE_NULL | MAY_BE_ARRAY), /* enterAnonymousFunctionWithoutReflection $callableParameters */ - reg::packed(5303, MAY_BE_NULL | MAY_BE_ARRAY), /* enterAnonymousFunctionWithoutReflection $nativeCallableParameters */ - reg::packed(1476, 0, 1261), /* enterAnonymousFunctionWithoutReflection return */ - reg::packed(5391, 0, 5402), /* expressionTypeIsUnchangeable $typeHolder */ - reg::packed(1476, MAY_BE_BOOL), /* expressionTypeIsUnchangeable return */ - reg::packed(975, MAY_BE_ARRAY), /* invalidateStaticExpressions $expressionTypes */ - reg::packed(1476, MAY_BE_ARRAY), /* invalidateStaticExpressions return */ - reg::packed(5497, 0, 5511), /* enterArrowFunction $arrowFunction */ - reg::packed(5284, MAY_BE_NULL | MAY_BE_ARRAY), /* enterArrowFunction $callableParameters */ - reg::packed(5303, MAY_BE_NULL | MAY_BE_ARRAY, reg::NoString, false, false, 867), /* enterArrowFunction $nativeCallableParameters */ - reg::packed(1476, 0, 1261), /* enterArrowFunction return */ - reg::packed(5497, 0, 5511), /* enterArrowFunctionWithoutReflection $arrowFunction */ - reg::packed(5284, MAY_BE_NULL | MAY_BE_ARRAY), /* enterArrowFunctionWithoutReflection $callableParameters */ - reg::packed(5303, MAY_BE_NULL | MAY_BE_ARRAY), /* enterArrowFunctionWithoutReflection $nativeCallableParameters */ - reg::packed(1476, 0, 1261), /* enterArrowFunctionWithoutReflection return */ - reg::packed(3617, 0, 5600), /* isParameterValueNullable $parameter */ - reg::packed(1476, MAY_BE_BOOL), /* isParameterValueNullable return */ - reg::packed(4614, 0), /* getFunctionType $type */ - reg::packed(5646, MAY_BE_BOOL), /* getFunctionType $isNullable */ - reg::packed(5657, MAY_BE_BOOL), /* getFunctionType $isVariadic */ - reg::packed(1476, 0, 2162), /* getFunctionType return */ - reg::packed(3617, 0, 5600), /* getCallableParameterType $parameter */ - reg::packed(5284, MAY_BE_ARRAY), /* getCallableParameterType $callableParameters */ - reg::packed(5684, MAY_BE_LONG), /* getCallableParameterType $index */ - reg::packed(1476, 0, 2162), /* getCallableParameterType return */ - reg::packed(5284, MAY_BE_ARRAY), /* buildVariadicArrayTypeFromCallableParameters $callableParameters */ - reg::packed(5715, MAY_BE_LONG), /* buildVariadicArrayTypeFromCallableParameters $startIndex */ - reg::packed(1476, 0, 2162), /* buildVariadicArrayTypeFromCallableParameters return */ - reg::packed(5771, 0, 2162), /* intersectButNotNever $nativeType */ - reg::packed(5782, 0, 2162), /* intersectButNotNever $inferredType */ - reg::packed(1476, 0, 2162), /* intersectButNotNever return */ - reg::packed(1704, 0, 5816), /* enterMatch $expr */ - reg::packed(5843, 0, 2162), /* enterMatch $condType */ - reg::packed(5852, 0, 2162), /* enterMatch $condNativeType */ - reg::packed(1476, 0, 1261), /* enterMatch return */ - reg::packed(5107, 0, 1261), /* enterForeach $originalScope */ - reg::packed(5878, 0, 2241), /* enterForeach $iteratee */ - reg::packed(5887, 0, 2162), /* enterForeach $iterateeType */ - reg::packed(5900, 0, 2162), /* enterForeach $nativeIterateeType */ - reg::packed(5919, MAY_BE_STRING), /* enterForeach $valueName */ - reg::packed(5929, MAY_BE_NULL | MAY_BE_STRING), /* enterForeach $keyName */ - reg::packed(5937, MAY_BE_BOOL), /* enterForeach $valueByRef */ - reg::packed(1476, 0, 1261), /* enterForeach return */ - reg::packed(5107, 0, 1261), /* enterForeachKey $originalScope */ - reg::packed(5878, 0, 2241), /* enterForeachKey $iteratee */ - reg::packed(5887, 0, 2162), /* enterForeachKey $iterateeType */ - reg::packed(5900, 0, 2162), /* enterForeachKey $nativeIterateeType */ - reg::packed(5929, MAY_BE_STRING), /* enterForeachKey $keyName */ - reg::packed(1476, 0, 1261), /* enterForeachKey return */ - reg::packed(5977, 0, 2162), /* enterCatchType $catchType */ - reg::packed(2112, MAY_BE_NULL | MAY_BE_STRING), /* enterCatchType $variableName */ - reg::packed(1476, 0, 1261), /* enterCatchType return */ - reg::packed(1704, 0, 2241), /* enterExpressionAssign $expr */ - reg::packed(6002, MAY_BE_BOOL, reg::NoString, false, false, 1140), /* enterExpressionAssign $isPlainWrite */ - reg::packed(1476, 0, 1261), /* enterExpressionAssign return */ - reg::packed(1704, 0, 2241), /* exitExpressionAssign $expr */ - reg::packed(1476, 0, 1261), /* exitExpressionAssign return */ - reg::packed(1704, 0, 2241), /* isInExpressionAssign $expr */ - reg::packed(1476, MAY_BE_BOOL), /* isInExpressionAssign return */ - reg::packed(1704, 0, 2241), /* isInWriteExpressionAssign $expr */ - reg::packed(1476, MAY_BE_BOOL), /* isInWriteExpressionAssign return */ - reg::packed(1704, 0, 2241), /* setAllowedUndefinedExpression $expr */ - reg::packed(1476, 0, 1261), /* setAllowedUndefinedExpression return */ - reg::packed(1704, 0, 2241), /* unsetAllowedUndefinedExpression $expr */ - reg::packed(1476, 0, 1261), /* unsetAllowedUndefinedExpression return */ - reg::packed(1704, 0, 2241), /* isUndefinedExpressionAllowed $expr */ - reg::packed(1476, MAY_BE_BOOL), /* isUndefinedExpressionAllowed return */ - reg::packed(2112, MAY_BE_STRING), /* assignVariable $variableName */ - reg::packed(4614, 0, 2162), /* assignVariable $type */ - reg::packed(5771, 0, 2162), /* assignVariable $nativeType */ - reg::packed(6196, 0, 2125), /* assignVariable $certainty */ - reg::packed(6206, MAY_BE_ARRAY, reg::NoString, false, false, 991), /* assignVariable $intertwinedPropagatedFrom */ - reg::packed(1476, 0, 1261), /* assignVariable return */ - reg::packed(1704, 0, 2241), /* overwriteExpression $expr */ - reg::packed(4614, 0, 2162), /* overwriteExpression $type */ - reg::packed(5771, 0, 2162), /* overwriteExpression $nativeType */ - reg::packed(1476, 0, 1261), /* overwriteExpression return */ - reg::packed(6267, 0, 1261), /* resolveIntertwinedAssignedType $scope */ - reg::packed(6273, 0, 2162), /* resolveIntertwinedAssignedType $rootType */ - reg::packed(6282, 0, 2241), /* resolveIntertwinedAssignedType $assignedExpr */ - reg::packed(6295, MAY_BE_STRING), /* resolveIntertwinedAssignedType $rootVariableName */ - reg::packed(6312, MAY_BE_BOOL), /* resolveIntertwinedAssignedType $native */ - reg::packed(1476, 0, 2162), /* resolveIntertwinedAssignedType return */ - reg::packed(6267, 0, 1261), /* isDimFetchPathReachable $scope */ - reg::packed(6350, 0, 6359), /* isDimFetchPathReachable $dimFetch */ - reg::packed(1476, MAY_BE_BOOL), /* isDimFetchPathReachable return */ - reg::packed(1704, 0, 2241), /* unsetExpression $expr */ - reg::packed(1476, 0, 1261), /* unsetExpression return */ - reg::packed(1704, 0, 2241), /* getStateType $expr */ - reg::packed(1476, 0, 2162), /* getStateType return */ - reg::packed(1704, 0, 2241), /* getScopeStateType $expr */ - reg::packed(1476, 0, 2162), /* getScopeStateType return */ - reg::packed(1704, 0, 2241), /* getScopeStateNativeType $expr */ - reg::packed(1476, 0, 2162), /* getScopeStateNativeType return */ - reg::packed(1704, 0, 2241), /* resolveScopeStateType $expr */ - reg::packed(6312, MAY_BE_BOOL), /* resolveScopeStateType $native */ - reg::packed(1476, 0, 2162), /* resolveScopeStateType return */ - reg::packed(1704, 0, 2241), /* specifyExpressionType $expr */ - reg::packed(4614, 0, 2162), /* specifyExpressionType $type */ - reg::packed(5771, 0, 2162), /* specifyExpressionType $nativeType */ - reg::packed(6196, 0, 2125), /* specifyExpressionType $certainty */ - reg::packed(1476, 0, 1261), /* specifyExpressionType return */ - reg::packed(1476, 0, 1261), /* openSpecificationScope return */ - reg::packed(1704, 0, 2241), /* isSpecifyExpressionTypeNoop $expr */ - reg::packed(4614, 0, 2162), /* isSpecifyExpressionTypeNoop $type */ - reg::packed(1476, MAY_BE_BOOL), /* isSpecifyExpressionTypeNoop return */ - reg::packed(1704, 0, 2241), /* specifyExpressionTypeInPlace $expr */ - reg::packed(4614, 0, 2162), /* specifyExpressionTypeInPlace $type */ - reg::packed(5771, 0, 2162), /* specifyExpressionTypeInPlace $nativeType */ - reg::packed(6196, 0, 2125), /* specifyExpressionTypeInPlace $certainty */ - reg::packed(1476, MAY_BE_VOID), /* specifyExpressionTypeInPlace return */ - reg::packed(1704, 0, 2241), /* assignExpression $expr */ - reg::packed(4614, 0, 2162), /* assignExpression $type */ - reg::packed(5771, 0, 2162), /* assignExpression $nativeType */ - reg::packed(1476, 0, 1261), /* assignExpression return */ - reg::packed(6629, 0, 2162), /* assignInitializedProperty $fetchedOnType */ - reg::packed(4468, MAY_BE_STRING), /* assignInitializedProperty $propertyName */ - reg::packed(1476, 0, 1261), /* assignInitializedProperty return */ - reg::packed(6669, 0, 2241), /* invalidateExpression $expressionToInvalidate */ - reg::packed(6692, MAY_BE_BOOL, reg::NoString, false, false, 891), /* invalidateExpression $requireMoreCharacters */ - reg::packed(6714, MAY_BE_NULL, 1803, false, false, 867), /* invalidateExpression $invalidatingClass */ - reg::packed(6732, MAY_BE_BOOL, reg::NoString, false, false, 891), /* invalidateExpression $keepPropertyFetches */ - reg::packed(1476, 0, 1261), /* invalidateExpression return */ - reg::packed(1704, 0, 2241), /* isPrivatePropertyOfDifferentClass $expr */ - reg::packed(6714, 0, 1803), /* isPrivatePropertyOfDifferentClass $invalidatingClass */ - reg::packed(1476, MAY_BE_BOOL), /* isPrivatePropertyOfDifferentClass return */ - reg::packed(6669, 0, 2241), /* invalidateMethodsOnExpression $expressionToInvalidate */ - reg::packed(1476, 0, 1261), /* invalidateMethodsOnExpression return */ - reg::packed(1704, 0, 2241), /* setExpressionCertaintyKeepingType $expr */ - reg::packed(6196, 0, 2125), /* setExpressionCertaintyKeepingType $certainty */ - reg::packed(1476, 0, 1261), /* setExpressionCertaintyKeepingType return */ - reg::packed(4614, 0, 2162), /* isComplexUnionType $type */ - reg::packed(1476, MAY_BE_BOOL), /* isComplexUnionType return */ - reg::packed(1704, 0, 2241), /* addTypeToExpression $expr */ - reg::packed(4614, 0, 2162), /* addTypeToExpression $type */ - reg::packed(1476, 0, 1261), /* addTypeToExpression return */ - reg::packed(1704, 0, 2241), /* removeTypeFromExpression $expr */ - reg::packed(6910, 0, 2162), /* removeTypeFromExpression $typeToRemove */ - reg::packed(1476, 0, 1261), /* removeTypeFromExpression return */ - reg::packed(1704, 0, 2241), /* filterByTruthyValue $expr */ - reg::packed(1476, 0, 1261), /* filterByTruthyValue return */ - reg::packed(1704, 0, 2241), /* filterByFalseyValue $expr */ - reg::packed(1476, 0, 1261), /* filterByFalseyValue return */ - reg::packed(6988, 0, 2775), /* applySpecifiedTypes $specifiedTypes */ - reg::packed(1476, 0, 1261), /* applySpecifiedTypes return */ - reg::packed(7023, MAY_BE_ARRAY), /* processConditionalExpressionsAfterSpecifying $specifiedExpressions */ - reg::packed(1476, 0, 1261), /* processConditionalExpressionsAfterSpecifying return */ - reg::packed(1476, MAY_BE_ARRAY), /* getConditionalExpressions return */ - reg::packed(2623, MAY_BE_STRING), /* addConditionalExpressions $exprString */ - reg::packed(7115, MAY_BE_ARRAY), /* addConditionalExpressions $conditionalExpressionHolders */ - reg::packed(1476, 0, 1261), /* addConditionalExpressions return */ - reg::packed(1476, 0, 1261), /* exitFirstLevelStatements return */ - reg::packed(1476, MAY_BE_BOOL), /* isInFirstLevelStatement return */ - reg::packed(7219, MAY_BE_NULL, 1261), /* mergeWith $otherScope */ - reg::packed(7230, MAY_BE_BOOL, reg::NoString, false, false, 891), /* mergeWith $preserveVacuousConditionals */ - reg::packed(1476, 0, 1261), /* mergeWith return */ - reg::packed(7268, 0, 1261), /* collectAbsorbedClosures $ours */ - reg::packed(7273, 0, 1261), /* collectAbsorbedClosures $theirs */ - reg::packed(1476, MAY_BE_NULL, 1410), /* collectAbsorbedClosures return */ - reg::packed(7219, MAY_BE_NULL, 1261), /* mergeWithVariableState $otherScope */ - reg::packed(7230, MAY_BE_BOOL, reg::NoString, false, false, 891), /* mergeWithVariableState $preserveVacuousConditionals */ - reg::packed(1476, 0, 1261), /* mergeWithVariableState return */ - reg::packed(7327, MAY_BE_ARRAY), /* withoutPreciseClassConstantFetches $differingExpressionKeys */ - reg::packed(7351, MAY_BE_ARRAY), /* withoutPreciseClassConstantFetches $ourExpressionTypes */ - reg::packed(7370, MAY_BE_ARRAY), /* withoutPreciseClassConstantFetches $theirExpressionTypes */ - reg::packed(1476, MAY_BE_ARRAY), /* withoutPreciseClassConstantFetches return */ - reg::packed(7426, MAY_BE_ARRAY), /* preserveVacuousConditionalExpressions $currentConditionalExpressions */ - reg::packed(7456, MAY_BE_ARRAY), /* preserveVacuousConditionalExpressions $sourceConditionalExpressions */ - reg::packed(7485, MAY_BE_ARRAY), /* preserveVacuousConditionalExpressions $otherExpressionTypes */ - reg::packed(1476, MAY_BE_ARRAY), /* preserveVacuousConditionalExpressions return */ - reg::packed(7426, MAY_BE_ARRAY), /* mergeSameGuardConditionalExpressions $currentConditionalExpressions */ - reg::packed(7544, MAY_BE_ARRAY), /* mergeSameGuardConditionalExpressions $ourConditionalExpressions */ - reg::packed(7570, MAY_BE_ARRAY), /* mergeSameGuardConditionalExpressions $theirConditionalExpressions */ - reg::packed(1476, MAY_BE_ARRAY), /* mergeSameGuardConditionalExpressions return */ - reg::packed(7635, MAY_BE_ARRAY), /* mergeConditionalExpressions $newConditionalExpressions */ - reg::packed(7661, MAY_BE_ARRAY), /* mergeConditionalExpressions $existingConditionalExpressions */ - reg::packed(1476, MAY_BE_ARRAY), /* mergeConditionalExpressions return */ - reg::packed(7720, 0, 1261), /* mergeInitializedProperties $calledMethodScope */ - reg::packed(1476, 0, 1261), /* mergeInitializedProperties return */ - reg::packed(7765, 0, 1261), /* processFinallyScope $finallyScope */ - reg::packed(7778, 0, 1261), /* processFinallyScope $originalFinallyScope */ - reg::packed(1476, 0, 1261), /* processFinallyScope return */ - reg::packed(7819, MAY_BE_ARRAY), /* processFinallyScopeVariableTypeHolders $ourVariableTypeHolders */ - reg::packed(7842, MAY_BE_ARRAY), /* processFinallyScopeVariableTypeHolders $finallyVariableTypeHolders */ - reg::packed(7869, MAY_BE_ARRAY), /* processFinallyScopeVariableTypeHolders $originalVariableTypeHolders */ - reg::packed(1476, MAY_BE_ARRAY), /* processFinallyScopeVariableTypeHolders return */ - reg::packed(7936, 0, 1261), /* processClosureScope $closureScope */ - reg::packed(7949, MAY_BE_NULL, 1261), /* processClosureScope $prevScope */ - reg::packed(7959, MAY_BE_ARRAY), /* processClosureScope $byRefUses */ - reg::packed(1476, 0, 1261), /* processClosureScope return */ - reg::packed(7989, 0, 1261), /* processAlwaysIterableForeachScopeWithoutPollute $finalScope */ - reg::packed(1476, 0, 1261), /* processAlwaysIterableForeachScopeWithoutPollute return */ - reg::packed(7219, 0, 1261), /* generalizeWith $otherScope */ - reg::packed(8048, MAY_BE_NULL | MAY_BE_ARRAY, reg::NoString, false, false, 867), /* generalizeWith $writableVariableNames */ - reg::packed(1476, 0, 1261), /* generalizeWith return */ - reg::packed(7219, 0, 1261), /* generalizeWithVariableState $otherScope */ - reg::packed(8048, MAY_BE_NULL | MAY_BE_ARRAY), /* generalizeWithVariableState $writableVariableNames */ - reg::packed(1476, 0, 1261), /* generalizeWithVariableState return */ - reg::packed(8113, MAY_BE_ARRAY), /* generalizeVariableTypeHolders $variableTypeHolders */ - reg::packed(8133, MAY_BE_ARRAY), /* generalizeVariableTypeHolders $otherVariableTypeHolders */ - reg::packed(8048, MAY_BE_NULL | MAY_BE_ARRAY), /* generalizeVariableTypeHolders $writableVariableNames */ - reg::packed(1476, MAY_BE_ARRAY), /* generalizeVariableTypeHolders return */ - reg::packed(4614, 0, 2162), /* flattenUnionForGeneralization $type */ - reg::packed(1476, MAY_BE_ARRAY), /* flattenUnionForGeneralization return */ - reg::packed(8218, 0, 2162), /* generalizeType $a */ - reg::packed(8220, 0, 2162), /* generalizeType $b */ - reg::packed(8222, MAY_BE_LONG), /* generalizeType $depth */ - reg::packed(1476, 0, 2162), /* generalizeType return */ - reg::packed(4614, 0, 2162), /* getArrayDepth $type */ - reg::packed(1476, MAY_BE_LONG), /* getArrayDepth return */ - reg::packed(7219, 0, 1261), /* equals $otherScope */ - reg::packed(1476, MAY_BE_BOOL), /* equals return */ - reg::packed(1016, MAY_BE_ARRAY), /* compareConditionalExpressions $conditionalExpressions */ - reg::packed(8264, MAY_BE_ARRAY), /* compareConditionalExpressions $otherConditionalExpressions */ - reg::packed(1476, MAY_BE_BOOL), /* compareConditionalExpressions return */ - reg::packed(8113, MAY_BE_ARRAY), /* compareVariableTypeHolders $variableTypeHolders */ - reg::packed(8133, MAY_BE_ARRAY), /* compareVariableTypeHolders $otherVariableTypeHolders */ - reg::packed(1476, MAY_BE_BOOL), /* compareVariableTypeHolders return */ - reg::packed(8349, 0, 8368), /* canAccessProperty $propertyReflection */ - reg::packed(1476, MAY_BE_BOOL), /* canAccessProperty return */ - reg::packed(8349, 0, 8424), /* canReadProperty $propertyReflection */ - reg::packed(1476, MAY_BE_BOOL), /* canReadProperty return */ - reg::packed(8349, 0, 8424), /* canWriteProperty $propertyReflection */ - reg::packed(1476, MAY_BE_BOOL), /* canWriteProperty return */ - reg::packed(8503, 0, 8520), /* canCallMethod $methodReflection */ - reg::packed(1476, MAY_BE_BOOL), /* canCallMethod return */ - reg::packed(8570, 0, 8589), /* canAccessConstant $constantReflection */ - reg::packed(1476, MAY_BE_BOOL), /* canAccessConstant return */ - reg::packed(8650, 0, 8672), /* canAccessClassMember $classMemberReflection */ - reg::packed(1476, MAY_BE_BOOL), /* canAccessClassMember return */ - reg::packed(1476, MAY_BE_ARRAY), /* debug return */ - reg::packed(8740, 0, 2162), /* filterTypeWithMethod $typeWithMethod */ - reg::packed(8755, MAY_BE_STRING), /* filterTypeWithMethod $methodName */ - reg::packed(1476, MAY_BE_NULL, 2162), /* filterTypeWithMethod return */ - reg::packed(8740, 0, 2162), /* getMethodReflection $typeWithMethod */ - reg::packed(8755, MAY_BE_STRING), /* getMethodReflection $methodName */ - reg::packed(1476, MAY_BE_NULL, 8787), /* getMethodReflection return */ - reg::packed(8740, 0, 2162), /* getNakedMethod $typeWithMethod */ - reg::packed(8755, MAY_BE_STRING), /* getNakedMethod $methodName */ - reg::packed(1476, MAY_BE_NULL, 8787), /* getNakedMethod return */ - reg::packed(8866, 0, 2162), /* getPropertyReflection $typeWithProperty */ - reg::packed(4468, MAY_BE_STRING), /* getPropertyReflection $propertyName */ - reg::packed(1476, MAY_BE_NULL, 8424), /* getPropertyReflection return */ - reg::packed(8866, 0, 2162), /* getInstancePropertyReflection $typeWithProperty */ - reg::packed(4468, MAY_BE_STRING), /* getInstancePropertyReflection $propertyName */ - reg::packed(1476, MAY_BE_NULL, 8424), /* getInstancePropertyReflection return */ - reg::packed(8866, 0, 2162), /* getStaticPropertyReflection $typeWithProperty */ - reg::packed(4468, MAY_BE_STRING), /* getStaticPropertyReflection $propertyName */ - reg::packed(1476, MAY_BE_NULL, 8424), /* getStaticPropertyReflection return */ - reg::packed(8963, 0, 2162), /* getConstantReflection $typeWithConstant */ - reg::packed(8980, MAY_BE_STRING), /* getConstantReflection $constantName */ - reg::packed(1476, MAY_BE_NULL, 8589), /* getConstantReflection return */ - reg::packed(8980, MAY_BE_STRING), /* getConstantExplicitTypeFromConfig $constantName */ - reg::packed(9015, 0, 2162), /* getConstantExplicitTypeFromConfig $constantType */ - reg::packed(1476, 0, 2162), /* getConstantExplicitTypeFromConfig return */ - reg::packed(1476, MAY_BE_ARRAY), /* getConstantTypes return */ - reg::packed(2313, 0, 2318), /* getGlobalConstantType $name */ - reg::packed(1476, MAY_BE_NULL, 2162), /* getGlobalConstantType return */ - reg::packed(2313, 0, 2318), /* createGlobalConstantFetches $name */ - reg::packed(9101, MAY_BE_STRING), /* createGlobalConstantFetches $nameString */ - reg::packed(965, MAY_BE_NULL | MAY_BE_STRING), /* createGlobalConstantFetches $namespace */ - reg::packed(1476, MAY_BE_ARRAY), /* createGlobalConstantFetches return */ - reg::packed(1476, MAY_BE_ARRAY), /* getNativeConstantTypes return */ - reg::packed(5878, 0, 2162), /* getIterableKeyType $iteratee */ - reg::packed(1476, 0, 2162), /* getIterableKeyType return */ - reg::packed(5878, 0, 2162), /* getIterableValueType $iteratee */ - reg::packed(1476, 0, 2162), /* getIterableValueType return */ - reg::packed(1476, 0, 9203), /* getPhpVersion return */ - reg::packed(4614, 0, 2162), /* isOverallPhpVersionRange $type */ - reg::packed(1476, MAY_BE_BOOL), /* isOverallPhpVersionRange return */ - reg::packed(2500, 0, 9266), /* invokeNodeCallback $node */ - reg::packed(1476, MAY_BE_VOID), /* invokeNodeCallback return */ - reg::packed(9300, MAY_BE_STRING), /* emitCollectedData $collectorType */ - reg::packed(9314, MAY_BE_ANY), /* emitCollectedData $data */ - reg::packed(1476, MAY_BE_VOID), /* emitCollectedData return */ - reg::packed(9337, MAY_BE_STRING), /* trackValueDependency $extensionClass */ - reg::packed(3280, MAY_BE_STRING), /* trackValueDependency $key */ - reg::packed(1476, MAY_BE_VOID), /* trackValueDependency return */ - reg::packed(9373, MAY_BE_STRING), /* trackFileDependency $file */ - reg::packed(1476, MAY_BE_VOID), /* trackFileDependency return */ - reg::packed(9398, MAY_BE_STRING), /* trackDirectoryDependency $directory */ - reg::packed(9408, MAY_BE_STRING, reg::NoString, false, false, 9416), /* trackDirectoryDependency $pattern */ - reg::packed(1476, MAY_BE_VOID), /* trackDirectoryDependency return */ - reg::packed(3717, MAY_BE_STRING), /* trackClassDependency $className */ - reg::packed(1476, MAY_BE_VOID), /* trackClassDependency return */ + reg::packed(0, 0, 9), /* __construct $services */ + reg::packed(40, 0, 53), /* __construct $scopeFactory */ + reg::packed(91, 0, 99), /* __construct $context */ + reg::packed(129, MAY_BE_BOOL, reg::NoString, false, false, 148), /* __construct $declareStrictTypes */ + reg::packed(154, MAY_BE_NULL, 163, false, false, 222), /* __construct $function */ + reg::packed(227, MAY_BE_NULL | MAY_BE_STRING, reg::NoString, false, false, 222), /* __construct $namespace */ + reg::packed(237, MAY_BE_ARRAY, reg::NoString, false, false, 253), /* __construct $expressionTypes */ + reg::packed(256, MAY_BE_ARRAY, reg::NoString, false, false, 253), /* __construct $nativeExpressionTypes */ + reg::packed(278, MAY_BE_ARRAY, reg::NoString, false, false, 253), /* __construct $conditionalExpressions */ + reg::packed(301, MAY_BE_ARRAY, reg::NoString, false, false, 253), /* __construct $inClosureBindScopeClasses */ + reg::packed(327, MAY_BE_NULL, 355, false, false, 222), /* __construct $anonymousFunctionReflection */ + reg::packed(380, MAY_BE_BOOL, reg::NoString, false, false, 402), /* __construct $inFirstLevelStatement */ + reg::packed(407, MAY_BE_ARRAY, reg::NoString, false, false, 253), /* __construct $currentlyAssignedExpressions */ + reg::packed(436, MAY_BE_ARRAY, reg::NoString, false, false, 253), /* __construct $currentlyAllowedUndefinedExpressions */ + reg::packed(473, MAY_BE_ARRAY, reg::NoString, false, false, 253), /* __construct $inFunctionCallsStack */ + reg::packed(494, MAY_BE_BOOL, reg::NoString, false, false, 148), /* __construct $afterExtractCall */ + reg::packed(511, MAY_BE_NULL, 523, false, false, 222), /* __construct $parentScope */ + reg::packed(554, MAY_BE_BOOL, reg::NoString, false, false, 148), /* __construct $nativeTypesPromoted */ + reg::packed(574, MAY_BE_NULL, 596, false, false, 222), /* __construct $templateArgumentFrame */ + reg::packed(644, MAY_BE_NULL, 672, false, false, 222), /* __construct $templateArgumentConstraints */ + reg::packed(738, 0, 523), /* toNodeCallbackScope return */ + reg::packed(738, 0, 523), /* toWalkScope return */ + reg::packed(738, 0, 523), /* toMutatingScope return */ + reg::packed(738, MAY_BE_STRING), /* getFile return */ + reg::packed(738, MAY_BE_STRING), /* getFileDescription return */ + reg::packed(738, MAY_BE_BOOL), /* isDeclareStrictTypes return */ + reg::packed(738, 0, 523), /* enterDeclareStrictTypes return */ + reg::packed(859, MAY_BE_ARRAY), /* rememberConstructorExpressions $currentExpressionTypes */ + reg::packed(738, MAY_BE_ARRAY), /* rememberConstructorExpressions return */ + reg::packed(738, MAY_BE_BOOL), /* classHasCustomSerialization return */ + reg::packed(738, 0, 523), /* rememberConstructorScope return */ + reg::packed(966, 0, 971), /* isReadonlyPropertyFetch $expr */ + reg::packed(1005, MAY_BE_BOOL), /* isReadonlyPropertyFetch $allowOnlyOnThis */ + reg::packed(738, MAY_BE_BOOL), /* isReadonlyPropertyFetch return */ + reg::packed(738, MAY_BE_BOOL), /* isInClass return */ + reg::packed(738, MAY_BE_BOOL), /* isInTrait return */ + reg::packed(738, MAY_BE_NULL, 1065), /* getClassReflection return */ + reg::packed(738, MAY_BE_NULL, 1065), /* getTraitReflection return */ + reg::packed(738, MAY_BE_NULL, 163), /* getFunction return */ + reg::packed(738, MAY_BE_NULL | MAY_BE_STRING), /* getFunctionName return */ + reg::packed(738, MAY_BE_NULL | MAY_BE_STRING), /* getNamespace return */ + reg::packed(738, MAY_BE_NULL, 523), /* getParentScope return */ + reg::packed(738, MAY_BE_BOOL), /* canAnyVariableExist return */ + reg::packed(738, 0, 523), /* afterExtractCall return */ + reg::packed(738, 0, 523), /* afterClearstatcacheCall return */ + reg::packed(1238, MAY_BE_STRING), /* afterOpenSslCall $openSslFunctionName */ + reg::packed(738, 0, 523), /* afterOpenSslCall return */ + reg::packed(738, 0, 523), /* invalidateVolatileExpressions return */ + reg::packed(1305, MAY_BE_ARRAY), /* invalidateExistenceCheckExpressions $functionNames */ + reg::packed(1319, MAY_BE_NULL | MAY_BE_STRING), /* invalidateExistenceCheckExpressions $declaredSymbolName */ + reg::packed(738, 0, 523), /* invalidateExistenceCheckExpressions return */ + reg::packed(1374, MAY_BE_STRING), /* hasVariableType $variableName */ + reg::packed(738, 0, 1387), /* hasVariableType return */ + reg::packed(1374, MAY_BE_STRING), /* getVariableType $variableName */ + reg::packed(738, 0, 1424), /* getVariableType return */ + reg::packed(738, MAY_BE_ARRAY), /* getDefinedVariables return */ + reg::packed(738, MAY_BE_ARRAY), /* getMaybeDefinedVariables return */ + reg::packed(966, 0, 1503), /* findPossiblyImpureCallDescriptions $expr */ + reg::packed(738, MAY_BE_ARRAY), /* findPossiblyImpureCallDescriptions return */ + reg::packed(1374, MAY_BE_STRING), /* isGlobalVariable $variableName */ + reg::packed(738, MAY_BE_BOOL), /* isGlobalVariable return */ + reg::packed(1575, 0, 1580), /* hasConstant $name */ + reg::packed(738, MAY_BE_BOOL), /* hasConstant return */ + reg::packed(738, MAY_BE_BOOL), /* fileHasCompilerHaltStatementCalls return */ + reg::packed(738, MAY_BE_BOOL), /* isInAnonymousFunction return */ + reg::packed(738, MAY_BE_NULL, 355), /* getAnonymousFunctionReflection return */ + reg::packed(738, MAY_BE_NULL, 1424), /* getAnonymousFunctionReturnType return */ + reg::packed(327, 0, 355), /* withAnonymousFunctionReflection $anonymousFunctionReflection */ + reg::packed(738, 0, 523), /* withAnonymousFunctionReflection return */ + reg::packed(1762, 0, 1503), /* getType $node */ + reg::packed(738, 0, 1424), /* getType return */ + reg::packed(966, 0, 1503), /* getScopeType $expr */ + reg::packed(738, 0, 1424), /* getScopeType return */ + reg::packed(966, 0, 1503), /* getScopeNativeType $expr */ + reg::packed(738, 0, 1424), /* getScopeNativeType return */ + reg::packed(1762, 0, 1503), /* getNodeKey $node */ + reg::packed(738, MAY_BE_STRING), /* getNodeKey return */ + reg::packed(738, 0, 1818), /* getExprPrinter return */ + reg::packed(237, MAY_BE_ARRAY), /* duplicateWith $expressionTypes */ + reg::packed(256, MAY_BE_ARRAY), /* duplicateWith $nativeExpressionTypes */ + reg::packed(278, MAY_BE_ARRAY), /* duplicateWith $conditionalExpressions */ + reg::packed(407, MAY_BE_ARRAY), /* duplicateWith $currentlyAssignedExpressions */ + reg::packed(436, MAY_BE_ARRAY), /* duplicateWith $currentlyAllowedUndefinedExpressions */ + reg::packed(473, MAY_BE_ARRAY), /* duplicateWith $inFunctionCallsStack */ + reg::packed(380, MAY_BE_BOOL), /* duplicateWith $inFirstLevelStatement */ + reg::packed(494, MAY_BE_BOOL), /* duplicateWith $afterExtractCall */ + reg::packed(738, 0, 523), /* duplicateWith return */ + reg::packed(1880, MAY_BE_NULL | MAY_BE_ARRAY, reg::NoString, false, false, 222), /* getClosureScopeCacheKey $relevantRoots */ + reg::packed(738, MAY_BE_STRING), /* getClosureScopeCacheKey return */ + reg::packed(1918, MAY_BE_STRING), /* exprStringIsRootedIn $exprString */ + reg::packed(1929, MAY_BE_ARRAY), /* exprStringIsRootedIn $roots */ + reg::packed(738, MAY_BE_BOOL), /* exprStringIsRootedIn return */ + reg::packed(1918, MAY_BE_STRING), /* resolveType $exprString */ + reg::packed(1762, 0, 1503), /* resolveType $node */ + reg::packed(738, 0, 1424), /* resolveType return */ + reg::packed(1762, 0, 1503), /* resolveTypeOfNewWorldHandlerNode $node */ + reg::packed(738, 0, 1424), /* resolveTypeOfNewWorldHandlerNode return */ + reg::packed(966, 0, 1503), /* getCurrentTypesOfSpecifiedExpr $expr */ + reg::packed(738, MAY_BE_NULL | MAY_BE_ARRAY), /* getCurrentTypesOfSpecifiedExpr return */ + reg::packed(1762, 0, 1503), /* specifyTypesOfNewWorldHandlerNode $node */ + reg::packed(91, 0, 2032), /* specifyTypesOfNewWorldHandlerNode $context */ + reg::packed(738, 0, 2070), /* specifyTypesOfNewWorldHandlerNode return */ + reg::packed(1762, 0, 1503), /* obtainResultForNode $node */ + reg::packed(738, 0, 2136), /* obtainResultForNode return */ + reg::packed(2190, 0, 2198), /* pushExpressionResultStorage $storage */ + reg::packed(738, MAY_BE_VOID), /* pushExpressionResultStorage return */ + reg::packed(738, MAY_BE_VOID), /* popExpressionResultStorage return */ + reg::packed(1762, 0, 1503), /* findSettledStoredResult $node */ + reg::packed(738, MAY_BE_NULL, 2136), /* findSettledStoredResult return */ + reg::packed(738, MAY_BE_NULL, 2198), /* getCurrentExpressionResultStorage return */ + reg::packed(2352, MAY_BE_NULL, 596), /* withTemplateArgumentFrame $frame */ + reg::packed(738, 0, 523), /* withTemplateArgumentFrame return */ + reg::packed(738, MAY_BE_NULL, 596), /* getCurrentTemplateArgumentFrame return */ + reg::packed(738, MAY_BE_NULL, 672), /* getTemplateArgumentConstraints return */ + reg::packed(2447, MAY_BE_NULL, 672), /* withTemplateArgumentConstraints $constraints */ + reg::packed(738, 0, 523), /* withTemplateArgumentConstraints return */ + reg::packed(2447, MAY_BE_NULL, 672), /* addTemplateArgumentConstraints $constraints */ + reg::packed(738, 0, 523), /* addTemplateArgumentConstraints return */ + reg::packed(738, 0, 523), /* withoutMemoizedTypes return */ + reg::packed(2543, 0, 523), /* getDifferingVariableRoots $other */ + reg::packed(738, MAY_BE_NULL | MAY_BE_ARRAY), /* getDifferingVariableRoots return */ + reg::packed(2575, MAY_BE_STRING), /* getVariablesOfExpressionKey $key */ + reg::packed(738, MAY_BE_NULL | MAY_BE_ARRAY), /* getVariablesOfExpressionKey return */ + reg::packed(2607, 0, 523), /* withRecordedStatementDelta $recordedEntry */ + reg::packed(2621, 0, 523), /* withRecordedStatementDelta $recordedExit */ + reg::packed(738, 0, 523), /* withRecordedStatementDelta return */ + reg::packed(2661, MAY_BE_ARRAY), /* applyRecordedHolderDelta $current */ + reg::packed(2607, MAY_BE_ARRAY), /* applyRecordedHolderDelta $recordedEntry */ + reg::packed(2621, MAY_BE_ARRAY), /* applyRecordedHolderDelta $recordedExit */ + reg::packed(738, MAY_BE_ARRAY), /* applyRecordedHolderDelta return */ + reg::packed(966, 0, 1503), /* getNativeType $expr */ + reg::packed(738, 0, 1424), /* getNativeType return */ + reg::packed(1762, 0, 1503), /* getKeepVoidType $node */ + reg::packed(738, 0, 1424), /* getKeepVoidType return */ + reg::packed(738, 0, 523), /* doNotTreatPhpDocTypesAsCertain return */ + reg::packed(738, 0, 523), /* promoteNativeTypes return */ + reg::packed(1575, 0, 1580), /* resolveName $name */ + reg::packed(738, MAY_BE_STRING), /* resolveName return */ + reg::packed(1575, 0, 1580), /* resolveTypeByName $name */ + reg::packed(738, 0, 2786), /* resolveTypeByName return */ + reg::packed(2835, 0), /* getTypeFromValue $value */ + reg::packed(738, 0, 1424), /* getTypeFromValue return */ + reg::packed(1762, 0, 1503), /* hasExpressionType $node */ + reg::packed(738, 0, 1387), /* hasExpressionType return */ + reg::packed(1762, 0, 1503), /* getTrackedExpressionType $node */ + reg::packed(738, 0, 1424), /* getTrackedExpressionType return */ + reg::packed(2901, 0), /* pushInFunctionCall $reflection */ + reg::packed(2912, MAY_BE_NULL, 2922), /* pushInFunctionCall $parameter */ + reg::packed(2961, MAY_BE_BOOL), /* pushInFunctionCall $rememberTypes */ + reg::packed(738, 0, 523), /* pushInFunctionCall return */ + reg::packed(738, 0, 523), /* popInFunctionCall return */ + reg::packed(3012, MAY_BE_STRING), /* isInClassExists $className */ + reg::packed(738, MAY_BE_BOOL), /* isInClassExists return */ + reg::packed(738, MAY_BE_ARRAY), /* getFunctionCallStack return */ + reg::packed(738, MAY_BE_ARRAY), /* getFunctionCallStackWithParameters return */ + reg::packed(3094, MAY_BE_STRING), /* isInFunctionExists $functionName */ + reg::packed(738, MAY_BE_BOOL), /* isInFunctionExists return */ + reg::packed(3126, 0, 1065), /* enterClass $classReflection */ + reg::packed(738, 0, 523), /* enterClass return */ + reg::packed(3153, 0, 1065), /* enterTrait $traitReflection */ + reg::packed(738, 0, 523), /* enterTrait return */ + reg::packed(3180, 0, 3192), /* enterClassMethod $classMethod */ + reg::packed(3224, 0, 3240), /* enterClassMethod $templateTypeMap */ + reg::packed(3277, MAY_BE_ARRAY), /* enterClassMethod $phpDocParameterTypes */ + reg::packed(3298, MAY_BE_NULL, 1424), /* enterClassMethod $phpDocReturnType */ + reg::packed(3315, MAY_BE_NULL, 1424), /* enterClassMethod $throwType */ + reg::packed(3325, MAY_BE_NULL | MAY_BE_STRING), /* enterClassMethod $deprecatedDescription */ + reg::packed(3347, MAY_BE_BOOL), /* enterClassMethod $isDeprecated */ + reg::packed(3360, MAY_BE_BOOL), /* enterClassMethod $isInternal */ + reg::packed(3371, MAY_BE_BOOL), /* enterClassMethod $isFinal */ + reg::packed(3379, MAY_BE_NULL | MAY_BE_BOOL, reg::NoString, false, false, 222), /* enterClassMethod $isPure */ + reg::packed(3386, MAY_BE_BOOL, reg::NoString, false, false, 402), /* enterClassMethod $acceptsNamedArguments */ + reg::packed(3408, MAY_BE_NULL, 3416, false, false, 222), /* enterClassMethod $asserts */ + reg::packed(3446, MAY_BE_NULL, 1424, false, false, 222), /* enterClassMethod $selfOutType */ + reg::packed(3458, MAY_BE_NULL | MAY_BE_STRING, reg::NoString, false, false, 222), /* enterClassMethod $phpDocComment */ + reg::packed(3472, MAY_BE_ARRAY, reg::NoString, false, false, 253), /* enterClassMethod $parameterOutTypes */ + reg::packed(3490, MAY_BE_ARRAY, reg::NoString, false, false, 253), /* enterClassMethod $immediatelyInvokedCallableParameters */ + reg::packed(3527, MAY_BE_ARRAY, reg::NoString, false, false, 253), /* enterClassMethod $phpDocClosureThisTypeParameters */ + reg::packed(3559, MAY_BE_BOOL, reg::NoString, false, false, 148), /* enterClassMethod $isConstructor */ + reg::packed(3573, MAY_BE_NULL, 3593, false, false, 222), /* enterClassMethod $resolvedPhpDocBlock */ + reg::packed(3628, MAY_BE_ARRAY, reg::NoString, false, false, 253), /* enterClassMethod $phpDocPureUnlessCallableIsImpureParameters */ + reg::packed(3671, MAY_BE_ARRAY, reg::NoString, false, false, 253), /* enterClassMethod $phpDocPureUnlessParameterPassedParameters */ + reg::packed(738, 0, 523), /* enterClassMethod return */ + reg::packed(3730, 0, 3735), /* enterPropertyHook $hook */ + reg::packed(3763, MAY_BE_STRING), /* enterPropertyHook $propertyName */ + reg::packed(3776, MAY_BE_NULL, 3799), /* enterPropertyHook $nativePropertyTypeNode */ + reg::packed(3872, MAY_BE_NULL, 1424), /* enterPropertyHook $phpDocPropertyType */ + reg::packed(3277, MAY_BE_ARRAY), /* enterPropertyHook $phpDocParameterTypes */ + reg::packed(3315, MAY_BE_NULL, 1424), /* enterPropertyHook $throwType */ + reg::packed(3325, MAY_BE_NULL | MAY_BE_STRING), /* enterPropertyHook $deprecatedDescription */ + reg::packed(3347, MAY_BE_BOOL), /* enterPropertyHook $isDeprecated */ + reg::packed(3379, MAY_BE_NULL | MAY_BE_BOOL), /* enterPropertyHook $isPure */ + reg::packed(3458, MAY_BE_NULL | MAY_BE_STRING), /* enterPropertyHook $phpDocComment */ + reg::packed(3573, MAY_BE_NULL, 3593, false, false, 222), /* enterPropertyHook $resolvedPhpDocBlock */ + reg::packed(738, 0, 523), /* enterPropertyHook return */ + reg::packed(3909, 0, 1424), /* transformStaticType $type */ + reg::packed(738, 0, 1424), /* transformStaticType return */ + reg::packed(3934, 0, 3947), /* getRealParameterTypes $functionLike */ + reg::packed(738, MAY_BE_ARRAY), /* getRealParameterTypes return */ + reg::packed(3934, 0, 3947), /* getRealParameterDefaultValues $functionLike */ + reg::packed(738, MAY_BE_ARRAY), /* getRealParameterDefaultValues return */ + reg::packed(3934, 0, 4027), /* getParameterAttributes $functionLike */ + reg::packed(738, MAY_BE_ARRAY), /* getParameterAttributes return */ + reg::packed(154, 0, 4140), /* enterFunction $function */ + reg::packed(3224, 0, 3240), /* enterFunction $templateTypeMap */ + reg::packed(3277, MAY_BE_ARRAY), /* enterFunction $phpDocParameterTypes */ + reg::packed(3298, MAY_BE_NULL, 1424), /* enterFunction $phpDocReturnType */ + reg::packed(3315, MAY_BE_NULL, 1424), /* enterFunction $throwType */ + reg::packed(3325, MAY_BE_NULL | MAY_BE_STRING), /* enterFunction $deprecatedDescription */ + reg::packed(3347, MAY_BE_BOOL), /* enterFunction $isDeprecated */ + reg::packed(3360, MAY_BE_BOOL), /* enterFunction $isInternal */ + reg::packed(3379, MAY_BE_NULL | MAY_BE_BOOL, reg::NoString, false, false, 222), /* enterFunction $isPure */ + reg::packed(3386, MAY_BE_BOOL, reg::NoString, false, false, 402), /* enterFunction $acceptsNamedArguments */ + reg::packed(3408, MAY_BE_NULL, 3416, false, false, 222), /* enterFunction $asserts */ + reg::packed(3458, MAY_BE_NULL | MAY_BE_STRING, reg::NoString, false, false, 222), /* enterFunction $phpDocComment */ + reg::packed(3472, MAY_BE_ARRAY, reg::NoString, false, false, 253), /* enterFunction $parameterOutTypes */ + reg::packed(3490, MAY_BE_ARRAY, reg::NoString, false, false, 253), /* enterFunction $immediatelyInvokedCallableParameters */ + reg::packed(3527, MAY_BE_ARRAY, reg::NoString, false, false, 253), /* enterFunction $phpDocClosureThisTypeParameters */ + reg::packed(4170, MAY_BE_ARRAY, reg::NoString, false, false, 253), /* enterFunction $pureUnlessCallableIsImpureParameters */ + reg::packed(4207, MAY_BE_ARRAY, reg::NoString, false, false, 253), /* enterFunction $pureUnlessParameterPassedParameters */ + reg::packed(738, 0, 523), /* enterFunction return */ + reg::packed(4257, 0, 163), /* enterFunctionLike $functionReflection */ + reg::packed(4276, MAY_BE_BOOL), /* enterFunctionLike $preserveConstructorScope */ + reg::packed(738, 0, 523), /* enterFunctionLike return */ + reg::packed(4319, MAY_BE_STRING), /* enterNamespace $namespaceName */ + reg::packed(738, 0, 523), /* enterNamespace return */ + reg::packed(4348, MAY_BE_NULL, 1424), /* enterClosureBind $thisType */ + reg::packed(4357, MAY_BE_NULL, 1424), /* enterClosureBind $nativeThisType */ + reg::packed(4372, MAY_BE_ARRAY), /* enterClosureBind $scopeClasses */ + reg::packed(738, 0, 523), /* enterClosureBind return */ + reg::packed(4402, 0, 523), /* restoreOriginalScopeAfterClosureBind $originalScope */ + reg::packed(738, 0, 523), /* restoreOriginalScopeAfterClosureBind return */ + reg::packed(4453, 0, 523), /* restoreThis $restoreThisScope */ + reg::packed(738, 0, 523), /* restoreThis return */ + reg::packed(4348, 0, 1424), /* enterClosureCall $thisType */ + reg::packed(4357, 0, 1424), /* enterClosureCall $nativeThisType */ + reg::packed(738, 0, 523), /* enterClosureCall return */ + reg::packed(738, MAY_BE_BOOL), /* isInClosureBind return */ + reg::packed(4372, MAY_BE_ARRAY), /* withClosureBindScopeClasses $scopeClasses */ + reg::packed(738, 0, 523), /* withClosureBindScopeClasses return */ + reg::packed(4543, 0, 4551), /* enterAnonymousFunction $closure */ + reg::packed(4579, MAY_BE_NULL | MAY_BE_ARRAY), /* enterAnonymousFunction $callableParameters */ + reg::packed(4598, MAY_BE_NULL | MAY_BE_ARRAY, reg::NoString, false, false, 222), /* enterAnonymousFunction $nativeCallableParameters */ + reg::packed(738, 0, 523), /* enterAnonymousFunction return */ + reg::packed(4543, 0, 4551), /* enterAnonymousFunctionWithoutReflection $closure */ + reg::packed(4579, MAY_BE_NULL | MAY_BE_ARRAY), /* enterAnonymousFunctionWithoutReflection $callableParameters */ + reg::packed(4598, MAY_BE_NULL | MAY_BE_ARRAY), /* enterAnonymousFunctionWithoutReflection $nativeCallableParameters */ + reg::packed(738, 0, 523), /* enterAnonymousFunctionWithoutReflection return */ + reg::packed(4686, 0, 4697), /* expressionTypeIsUnchangeable $typeHolder */ + reg::packed(738, MAY_BE_BOOL), /* expressionTypeIsUnchangeable return */ + reg::packed(237, MAY_BE_ARRAY), /* invalidateStaticExpressions $expressionTypes */ + reg::packed(738, MAY_BE_ARRAY), /* invalidateStaticExpressions return */ + reg::packed(4792, 0, 4806), /* enterArrowFunction $arrowFunction */ + reg::packed(4579, MAY_BE_NULL | MAY_BE_ARRAY), /* enterArrowFunction $callableParameters */ + reg::packed(4598, MAY_BE_NULL | MAY_BE_ARRAY, reg::NoString, false, false, 222), /* enterArrowFunction $nativeCallableParameters */ + reg::packed(738, 0, 523), /* enterArrowFunction return */ + reg::packed(4792, 0, 4806), /* enterArrowFunctionWithoutReflection $arrowFunction */ + reg::packed(4579, MAY_BE_NULL | MAY_BE_ARRAY), /* enterArrowFunctionWithoutReflection $callableParameters */ + reg::packed(4598, MAY_BE_NULL | MAY_BE_ARRAY), /* enterArrowFunctionWithoutReflection $nativeCallableParameters */ + reg::packed(738, 0, 523), /* enterArrowFunctionWithoutReflection return */ + reg::packed(2912, 0, 4895), /* isParameterValueNullable $parameter */ + reg::packed(738, MAY_BE_BOOL), /* isParameterValueNullable return */ + reg::packed(3909, 0), /* getFunctionType $type */ + reg::packed(4941, MAY_BE_BOOL), /* getFunctionType $isNullable */ + reg::packed(4952, MAY_BE_BOOL), /* getFunctionType $isVariadic */ + reg::packed(738, 0, 1424), /* getFunctionType return */ + reg::packed(2912, 0, 4895), /* getCallableParameterType $parameter */ + reg::packed(4579, MAY_BE_ARRAY), /* getCallableParameterType $callableParameters */ + reg::packed(4979, MAY_BE_LONG), /* getCallableParameterType $index */ + reg::packed(738, 0, 1424), /* getCallableParameterType return */ + reg::packed(4579, MAY_BE_ARRAY), /* buildVariadicArrayTypeFromCallableParameters $callableParameters */ + reg::packed(5010, MAY_BE_LONG), /* buildVariadicArrayTypeFromCallableParameters $startIndex */ + reg::packed(738, 0, 1424), /* buildVariadicArrayTypeFromCallableParameters return */ + reg::packed(5066, 0, 1424), /* intersectButNotNever $nativeType */ + reg::packed(5077, 0, 1424), /* intersectButNotNever $inferredType */ + reg::packed(738, 0, 1424), /* intersectButNotNever return */ + reg::packed(966, 0, 5111), /* enterMatch $expr */ + reg::packed(5138, 0, 1424), /* enterMatch $condType */ + reg::packed(5147, 0, 1424), /* enterMatch $condNativeType */ + reg::packed(738, 0, 523), /* enterMatch return */ + reg::packed(4402, 0, 523), /* enterForeach $originalScope */ + reg::packed(5173, 0, 1503), /* enterForeach $iteratee */ + reg::packed(5182, 0, 1424), /* enterForeach $iterateeType */ + reg::packed(5195, 0, 1424), /* enterForeach $nativeIterateeType */ + reg::packed(5214, MAY_BE_STRING), /* enterForeach $valueName */ + reg::packed(5224, MAY_BE_NULL | MAY_BE_STRING), /* enterForeach $keyName */ + reg::packed(5232, MAY_BE_BOOL), /* enterForeach $valueByRef */ + reg::packed(738, 0, 523), /* enterForeach return */ + reg::packed(4402, 0, 523), /* enterForeachKey $originalScope */ + reg::packed(5173, 0, 1503), /* enterForeachKey $iteratee */ + reg::packed(5182, 0, 1424), /* enterForeachKey $iterateeType */ + reg::packed(5195, 0, 1424), /* enterForeachKey $nativeIterateeType */ + reg::packed(5224, MAY_BE_STRING), /* enterForeachKey $keyName */ + reg::packed(738, 0, 523), /* enterForeachKey return */ + reg::packed(5272, 0, 1424), /* enterCatchType $catchType */ + reg::packed(1374, MAY_BE_NULL | MAY_BE_STRING), /* enterCatchType $variableName */ + reg::packed(738, 0, 523), /* enterCatchType return */ + reg::packed(966, 0, 1503), /* enterExpressionAssign $expr */ + reg::packed(5297, MAY_BE_BOOL, reg::NoString, false, false, 402), /* enterExpressionAssign $isPlainWrite */ + reg::packed(738, 0, 523), /* enterExpressionAssign return */ + reg::packed(966, 0, 1503), /* exitExpressionAssign $expr */ + reg::packed(738, 0, 523), /* exitExpressionAssign return */ + reg::packed(966, 0, 1503), /* isInExpressionAssign $expr */ + reg::packed(738, MAY_BE_BOOL), /* isInExpressionAssign return */ + reg::packed(966, 0, 1503), /* isInWriteExpressionAssign $expr */ + reg::packed(738, MAY_BE_BOOL), /* isInWriteExpressionAssign return */ + reg::packed(966, 0, 1503), /* setAllowedUndefinedExpression $expr */ + reg::packed(738, 0, 523), /* setAllowedUndefinedExpression return */ + reg::packed(966, 0, 1503), /* unsetAllowedUndefinedExpression $expr */ + reg::packed(738, 0, 523), /* unsetAllowedUndefinedExpression return */ + reg::packed(966, 0, 1503), /* isUndefinedExpressionAllowed $expr */ + reg::packed(738, MAY_BE_BOOL), /* isUndefinedExpressionAllowed return */ + reg::packed(1374, MAY_BE_STRING), /* assignVariable $variableName */ + reg::packed(3909, 0, 1424), /* assignVariable $type */ + reg::packed(5066, 0, 1424), /* assignVariable $nativeType */ + reg::packed(5491, 0, 1387), /* assignVariable $certainty */ + reg::packed(5501, MAY_BE_ARRAY, reg::NoString, false, false, 253), /* assignVariable $intertwinedPropagatedFrom */ + reg::packed(738, 0, 523), /* assignVariable return */ + reg::packed(966, 0, 1503), /* overwriteExpression $expr */ + reg::packed(3909, 0, 1424), /* overwriteExpression $type */ + reg::packed(5066, 0, 1424), /* overwriteExpression $nativeType */ + reg::packed(738, 0, 523), /* overwriteExpression return */ + reg::packed(5562, 0, 523), /* resolveIntertwinedAssignedType $scope */ + reg::packed(5568, 0, 1424), /* resolveIntertwinedAssignedType $rootType */ + reg::packed(5577, 0, 1503), /* resolveIntertwinedAssignedType $assignedExpr */ + reg::packed(5590, MAY_BE_STRING), /* resolveIntertwinedAssignedType $rootVariableName */ + reg::packed(5607, MAY_BE_BOOL), /* resolveIntertwinedAssignedType $native */ + reg::packed(738, 0, 1424), /* resolveIntertwinedAssignedType return */ + reg::packed(5562, 0, 523), /* isDimFetchPathReachable $scope */ + reg::packed(5645, 0, 5654), /* isDimFetchPathReachable $dimFetch */ + reg::packed(738, MAY_BE_BOOL), /* isDimFetchPathReachable return */ + reg::packed(966, 0, 1503), /* unsetExpression $expr */ + reg::packed(738, 0, 523), /* unsetExpression return */ + reg::packed(966, 0, 1503), /* getStateType $expr */ + reg::packed(738, 0, 1424), /* getStateType return */ + reg::packed(966, 0, 1503), /* getScopeStateType $expr */ + reg::packed(738, 0, 1424), /* getScopeStateType return */ + reg::packed(966, 0, 1503), /* getScopeStateNativeType $expr */ + reg::packed(738, 0, 1424), /* getScopeStateNativeType return */ + reg::packed(966, 0, 1503), /* resolveScopeStateType $expr */ + reg::packed(5607, MAY_BE_BOOL), /* resolveScopeStateType $native */ + reg::packed(738, 0, 1424), /* resolveScopeStateType return */ + reg::packed(966, 0, 1503), /* specifyExpressionType $expr */ + reg::packed(3909, 0, 1424), /* specifyExpressionType $type */ + reg::packed(5066, 0, 1424), /* specifyExpressionType $nativeType */ + reg::packed(5491, 0, 1387), /* specifyExpressionType $certainty */ + reg::packed(738, 0, 523), /* specifyExpressionType return */ + reg::packed(738, 0, 523), /* openSpecificationScope return */ + reg::packed(966, 0, 1503), /* isSpecifyExpressionTypeNoop $expr */ + reg::packed(3909, 0, 1424), /* isSpecifyExpressionTypeNoop $type */ + reg::packed(738, MAY_BE_BOOL), /* isSpecifyExpressionTypeNoop return */ + reg::packed(966, 0, 1503), /* specifyExpressionTypeInPlace $expr */ + reg::packed(3909, 0, 1424), /* specifyExpressionTypeInPlace $type */ + reg::packed(5066, 0, 1424), /* specifyExpressionTypeInPlace $nativeType */ + reg::packed(5491, 0, 1387), /* specifyExpressionTypeInPlace $certainty */ + reg::packed(738, MAY_BE_VOID), /* specifyExpressionTypeInPlace return */ + reg::packed(966, 0, 1503), /* assignExpression $expr */ + reg::packed(3909, 0, 1424), /* assignExpression $type */ + reg::packed(5066, 0, 1424), /* assignExpression $nativeType */ + reg::packed(738, 0, 523), /* assignExpression return */ + reg::packed(5924, 0, 1424), /* assignInitializedProperty $fetchedOnType */ + reg::packed(3763, MAY_BE_STRING), /* assignInitializedProperty $propertyName */ + reg::packed(738, 0, 523), /* assignInitializedProperty return */ + reg::packed(5964, 0, 1503), /* invalidateExpression $expressionToInvalidate */ + reg::packed(5987, MAY_BE_BOOL, reg::NoString, false, false, 148), /* invalidateExpression $requireMoreCharacters */ + reg::packed(6009, MAY_BE_NULL, 1065, false, false, 222), /* invalidateExpression $invalidatingClass */ + reg::packed(6027, MAY_BE_BOOL, reg::NoString, false, false, 148), /* invalidateExpression $keepPropertyFetches */ + reg::packed(738, 0, 523), /* invalidateExpression return */ + reg::packed(966, 0, 1503), /* isPrivatePropertyOfDifferentClass $expr */ + reg::packed(6009, 0, 1065), /* isPrivatePropertyOfDifferentClass $invalidatingClass */ + reg::packed(738, MAY_BE_BOOL), /* isPrivatePropertyOfDifferentClass return */ + reg::packed(5964, 0, 1503), /* invalidateMethodsOnExpression $expressionToInvalidate */ + reg::packed(738, 0, 523), /* invalidateMethodsOnExpression return */ + reg::packed(966, 0, 1503), /* setExpressionCertaintyKeepingType $expr */ + reg::packed(5491, 0, 1387), /* setExpressionCertaintyKeepingType $certainty */ + reg::packed(738, 0, 523), /* setExpressionCertaintyKeepingType return */ + reg::packed(3909, 0, 1424), /* isComplexUnionType $type */ + reg::packed(738, MAY_BE_BOOL), /* isComplexUnionType return */ + reg::packed(966, 0, 1503), /* addTypeToExpression $expr */ + reg::packed(3909, 0, 1424), /* addTypeToExpression $type */ + reg::packed(738, 0, 523), /* addTypeToExpression return */ + reg::packed(966, 0, 1503), /* removeTypeFromExpression $expr */ + reg::packed(6205, 0, 1424), /* removeTypeFromExpression $typeToRemove */ + reg::packed(738, 0, 523), /* removeTypeFromExpression return */ + reg::packed(966, 0, 1503), /* filterByTruthyValue $expr */ + reg::packed(738, 0, 523), /* filterByTruthyValue return */ + reg::packed(966, 0, 1503), /* filterByFalseyValue $expr */ + reg::packed(738, 0, 523), /* filterByFalseyValue return */ + reg::packed(6283, 0, 2070), /* applySpecifiedTypes $specifiedTypes */ + reg::packed(738, 0, 523), /* applySpecifiedTypes return */ + reg::packed(6318, MAY_BE_ARRAY), /* processConditionalExpressionsAfterSpecifying $specifiedExpressions */ + reg::packed(738, 0, 523), /* processConditionalExpressionsAfterSpecifying return */ + reg::packed(738, MAY_BE_ARRAY), /* getConditionalExpressions return */ + reg::packed(1918, MAY_BE_STRING), /* addConditionalExpressions $exprString */ + reg::packed(6410, MAY_BE_ARRAY), /* addConditionalExpressions $conditionalExpressionHolders */ + reg::packed(738, 0, 523), /* addConditionalExpressions return */ + reg::packed(738, 0, 523), /* exitFirstLevelStatements return */ + reg::packed(738, MAY_BE_BOOL), /* isInFirstLevelStatement return */ + reg::packed(6514, MAY_BE_NULL, 523), /* mergeWith $otherScope */ + reg::packed(6525, MAY_BE_BOOL, reg::NoString, false, false, 148), /* mergeWith $preserveVacuousConditionals */ + reg::packed(738, 0, 523), /* mergeWith return */ + reg::packed(6563, 0, 523), /* collectAbsorbedClosures $ours */ + reg::packed(6568, 0, 523), /* collectAbsorbedClosures $theirs */ + reg::packed(738, MAY_BE_NULL, 672), /* collectAbsorbedClosures return */ + reg::packed(6514, MAY_BE_NULL, 523), /* mergeWithVariableState $otherScope */ + reg::packed(6525, MAY_BE_BOOL, reg::NoString, false, false, 148), /* mergeWithVariableState $preserveVacuousConditionals */ + reg::packed(738, 0, 523), /* mergeWithVariableState return */ + reg::packed(6622, MAY_BE_ARRAY), /* withoutPreciseClassConstantFetches $differingExpressionKeys */ + reg::packed(6646, MAY_BE_ARRAY), /* withoutPreciseClassConstantFetches $ourExpressionTypes */ + reg::packed(6665, MAY_BE_ARRAY), /* withoutPreciseClassConstantFetches $theirExpressionTypes */ + reg::packed(738, MAY_BE_ARRAY), /* withoutPreciseClassConstantFetches return */ + reg::packed(6721, MAY_BE_ARRAY), /* preserveVacuousConditionalExpressions $currentConditionalExpressions */ + reg::packed(6751, MAY_BE_ARRAY), /* preserveVacuousConditionalExpressions $sourceConditionalExpressions */ + reg::packed(6780, MAY_BE_ARRAY), /* preserveVacuousConditionalExpressions $otherExpressionTypes */ + reg::packed(738, MAY_BE_ARRAY), /* preserveVacuousConditionalExpressions return */ + reg::packed(6721, MAY_BE_ARRAY), /* mergeSameGuardConditionalExpressions $currentConditionalExpressions */ + reg::packed(6839, MAY_BE_ARRAY), /* mergeSameGuardConditionalExpressions $ourConditionalExpressions */ + reg::packed(6865, MAY_BE_ARRAY), /* mergeSameGuardConditionalExpressions $theirConditionalExpressions */ + reg::packed(738, MAY_BE_ARRAY), /* mergeSameGuardConditionalExpressions return */ + reg::packed(6930, MAY_BE_ARRAY), /* mergeConditionalExpressions $newConditionalExpressions */ + reg::packed(6956, MAY_BE_ARRAY), /* mergeConditionalExpressions $existingConditionalExpressions */ + reg::packed(738, MAY_BE_ARRAY), /* mergeConditionalExpressions return */ + reg::packed(7015, 0, 523), /* mergeInitializedProperties $calledMethodScope */ + reg::packed(738, 0, 523), /* mergeInitializedProperties return */ + reg::packed(7060, 0, 523), /* processFinallyScope $finallyScope */ + reg::packed(7073, 0, 523), /* processFinallyScope $originalFinallyScope */ + reg::packed(738, 0, 523), /* processFinallyScope return */ + reg::packed(7114, MAY_BE_ARRAY), /* processFinallyScopeVariableTypeHolders $ourVariableTypeHolders */ + reg::packed(7137, MAY_BE_ARRAY), /* processFinallyScopeVariableTypeHolders $finallyVariableTypeHolders */ + reg::packed(7164, MAY_BE_ARRAY), /* processFinallyScopeVariableTypeHolders $originalVariableTypeHolders */ + reg::packed(738, MAY_BE_ARRAY), /* processFinallyScopeVariableTypeHolders return */ + reg::packed(7231, 0, 523), /* processClosureScope $closureScope */ + reg::packed(7244, MAY_BE_NULL, 523), /* processClosureScope $prevScope */ + reg::packed(7254, MAY_BE_ARRAY), /* processClosureScope $byRefUses */ + reg::packed(738, 0, 523), /* processClosureScope return */ + reg::packed(7284, 0, 523), /* processAlwaysIterableForeachScopeWithoutPollute $finalScope */ + reg::packed(738, 0, 523), /* processAlwaysIterableForeachScopeWithoutPollute return */ + reg::packed(6514, 0, 523), /* generalizeWith $otherScope */ + reg::packed(7343, MAY_BE_NULL | MAY_BE_ARRAY, reg::NoString, false, false, 222), /* generalizeWith $writableVariableNames */ + reg::packed(738, 0, 523), /* generalizeWith return */ + reg::packed(6514, 0, 523), /* generalizeWithVariableState $otherScope */ + reg::packed(7343, MAY_BE_NULL | MAY_BE_ARRAY), /* generalizeWithVariableState $writableVariableNames */ + reg::packed(738, 0, 523), /* generalizeWithVariableState return */ + reg::packed(7408, MAY_BE_ARRAY), /* generalizeVariableTypeHolders $variableTypeHolders */ + reg::packed(7428, MAY_BE_ARRAY), /* generalizeVariableTypeHolders $otherVariableTypeHolders */ + reg::packed(7343, MAY_BE_NULL | MAY_BE_ARRAY), /* generalizeVariableTypeHolders $writableVariableNames */ + reg::packed(738, MAY_BE_ARRAY), /* generalizeVariableTypeHolders return */ + reg::packed(3909, 0, 1424), /* flattenUnionForGeneralization $type */ + reg::packed(738, MAY_BE_ARRAY), /* flattenUnionForGeneralization return */ + reg::packed(7513, 0, 1424), /* generalizeType $a */ + reg::packed(7515, 0, 1424), /* generalizeType $b */ + reg::packed(7517, MAY_BE_LONG), /* generalizeType $depth */ + reg::packed(738, 0, 1424), /* generalizeType return */ + reg::packed(3909, 0, 1424), /* getArrayDepth $type */ + reg::packed(738, MAY_BE_LONG), /* getArrayDepth return */ + reg::packed(6514, 0, 523), /* equals $otherScope */ + reg::packed(738, MAY_BE_BOOL), /* equals return */ + reg::packed(278, MAY_BE_ARRAY), /* compareConditionalExpressions $conditionalExpressions */ + reg::packed(7559, MAY_BE_ARRAY), /* compareConditionalExpressions $otherConditionalExpressions */ + reg::packed(738, MAY_BE_BOOL), /* compareConditionalExpressions return */ + reg::packed(7408, MAY_BE_ARRAY), /* compareVariableTypeHolders $variableTypeHolders */ + reg::packed(7428, MAY_BE_ARRAY), /* compareVariableTypeHolders $otherVariableTypeHolders */ + reg::packed(738, MAY_BE_BOOL), /* compareVariableTypeHolders return */ + reg::packed(7644, 0, 7663), /* canAccessProperty $propertyReflection */ + reg::packed(738, MAY_BE_BOOL), /* canAccessProperty return */ + reg::packed(7644, 0, 7719), /* canReadProperty $propertyReflection */ + reg::packed(738, MAY_BE_BOOL), /* canReadProperty return */ + reg::packed(7644, 0, 7719), /* canWriteProperty $propertyReflection */ + reg::packed(738, MAY_BE_BOOL), /* canWriteProperty return */ + reg::packed(7798, 0, 7815), /* canCallMethod $methodReflection */ + reg::packed(738, MAY_BE_BOOL), /* canCallMethod return */ + reg::packed(7865, 0, 7884), /* canAccessConstant $constantReflection */ + reg::packed(738, MAY_BE_BOOL), /* canAccessConstant return */ + reg::packed(7945, 0, 7967), /* canAccessClassMember $classMemberReflection */ + reg::packed(738, MAY_BE_BOOL), /* canAccessClassMember return */ + reg::packed(738, MAY_BE_ARRAY), /* debug return */ + reg::packed(8035, 0, 1424), /* filterTypeWithMethod $typeWithMethod */ + reg::packed(8050, MAY_BE_STRING), /* filterTypeWithMethod $methodName */ + reg::packed(738, MAY_BE_NULL, 1424), /* filterTypeWithMethod return */ + reg::packed(8035, 0, 1424), /* getMethodReflection $typeWithMethod */ + reg::packed(8050, MAY_BE_STRING), /* getMethodReflection $methodName */ + reg::packed(738, MAY_BE_NULL, 8082), /* getMethodReflection return */ + reg::packed(8035, 0, 1424), /* getNakedMethod $typeWithMethod */ + reg::packed(8050, MAY_BE_STRING), /* getNakedMethod $methodName */ + reg::packed(738, MAY_BE_NULL, 8082), /* getNakedMethod return */ + reg::packed(8161, 0, 1424), /* getPropertyReflection $typeWithProperty */ + reg::packed(3763, MAY_BE_STRING), /* getPropertyReflection $propertyName */ + reg::packed(738, MAY_BE_NULL, 7719), /* getPropertyReflection return */ + reg::packed(8161, 0, 1424), /* getInstancePropertyReflection $typeWithProperty */ + reg::packed(3763, MAY_BE_STRING), /* getInstancePropertyReflection $propertyName */ + reg::packed(738, MAY_BE_NULL, 7719), /* getInstancePropertyReflection return */ + reg::packed(8161, 0, 1424), /* getStaticPropertyReflection $typeWithProperty */ + reg::packed(3763, MAY_BE_STRING), /* getStaticPropertyReflection $propertyName */ + reg::packed(738, MAY_BE_NULL, 7719), /* getStaticPropertyReflection return */ + reg::packed(8258, 0, 1424), /* getConstantReflection $typeWithConstant */ + reg::packed(8275, MAY_BE_STRING), /* getConstantReflection $constantName */ + reg::packed(738, MAY_BE_NULL, 7884), /* getConstantReflection return */ + reg::packed(8275, MAY_BE_STRING), /* getConstantExplicitTypeFromConfig $constantName */ + reg::packed(8310, 0, 1424), /* getConstantExplicitTypeFromConfig $constantType */ + reg::packed(738, 0, 1424), /* getConstantExplicitTypeFromConfig return */ + reg::packed(738, MAY_BE_ARRAY), /* getConstantTypes return */ + reg::packed(1575, 0, 1580), /* getGlobalConstantType $name */ + reg::packed(738, MAY_BE_NULL, 1424), /* getGlobalConstantType return */ + reg::packed(1575, 0, 1580), /* createGlobalConstantFetches $name */ + reg::packed(8396, MAY_BE_STRING), /* createGlobalConstantFetches $nameString */ + reg::packed(227, MAY_BE_NULL | MAY_BE_STRING), /* createGlobalConstantFetches $namespace */ + reg::packed(738, MAY_BE_ARRAY), /* createGlobalConstantFetches return */ + reg::packed(738, MAY_BE_ARRAY), /* getNativeConstantTypes return */ + reg::packed(5173, 0, 1424), /* getIterableKeyType $iteratee */ + reg::packed(738, 0, 1424), /* getIterableKeyType return */ + reg::packed(5173, 0, 1424), /* getIterableValueType $iteratee */ + reg::packed(738, 0, 1424), /* getIterableValueType return */ + reg::packed(738, 0, 8498), /* getPhpVersion return */ + reg::packed(3909, 0, 1424), /* isOverallPhpVersionRange $type */ + reg::packed(738, MAY_BE_BOOL), /* isOverallPhpVersionRange return */ + reg::packed(1762, 0, 8561), /* invokeNodeCallback $node */ + reg::packed(738, MAY_BE_VOID), /* invokeNodeCallback return */ + reg::packed(8595, MAY_BE_STRING), /* emitCollectedData $collectorType */ + reg::packed(8609, MAY_BE_ANY), /* emitCollectedData $data */ + reg::packed(738, MAY_BE_VOID), /* emitCollectedData return */ + reg::packed(8632, MAY_BE_STRING), /* trackValueDependency $extensionClass */ + reg::packed(2575, MAY_BE_STRING), /* trackValueDependency $key */ + reg::packed(738, MAY_BE_VOID), /* trackValueDependency return */ + reg::packed(8668, MAY_BE_STRING), /* trackFileDependency $file */ + reg::packed(738, MAY_BE_VOID), /* trackFileDependency return */ + reg::packed(8693, MAY_BE_STRING), /* trackDirectoryDependency $directory */ + reg::packed(8703, MAY_BE_STRING, reg::NoString, false, false, 8711), /* trackDirectoryDependency $pattern */ + reg::packed(738, MAY_BE_VOID), /* trackDirectoryDependency return */ + reg::packed(3012, MAY_BE_STRING), /* trackClassDependency $className */ + reg::packed(738, MAY_BE_VOID), /* trackClassDependency return */ }; using Sig = reg::Sig; } // namespace sigtab /* the signatures of the methods the class declares itself (a used trait's are in the trait's header) */ namespace sig { -inline constexpr sigtab::Sig __construct = { { 1464 /* __construct */, 15, 0, 33, reg::NoArg, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig toNodeCallbackScope = { { 1477 /* toNodeCallbackScope */, 0, 33, 0, 33, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig toWalkScope = { { 1497 /* toWalkScope */, 0, 34, 0, 34, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig toMutatingScope = { { 1509 /* toMutatingScope */, 0, 35, 0, 35, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getFile = { { 1525 /* getFile */, 0, 36, 0, 36, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getFileDescription = { { 1533 /* getFileDescription */, 0, 37, 0, 37, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig isDeclareStrictTypes = { { 1552 /* isDeclareStrictTypes */, 0, 38, 0, 38, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig enterDeclareStrictTypes = { { 1573 /* enterDeclareStrictTypes */, 0, 39, 0, 39, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig rememberConstructorExpressions = { { 1620 /* rememberConstructorExpressions */, 1, 40, 1, 41, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig classHasCustomSerialization = { { 1651 /* classHasCustomSerialization */, 0, 42, 0, 42, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig rememberConstructorScope = { { 1679 /* rememberConstructorScope */, 0, 43, 0, 43, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig isReadonlyPropertyFetch = { { 1759 /* isReadonlyPropertyFetch */, 2, 44, 2, 46, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig isInClass = { { 1783 /* isInClass */, 0, 47, 0, 47, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig isInTrait = { { 1793 /* isInTrait */, 0, 48, 0, 48, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getClassReflection = { { 1838 /* getClassReflection */, 0, 49, 0, 49, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getTraitReflection = { { 1857 /* getTraitReflection */, 0, 50, 0, 50, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getFunction = { { 1876 /* getFunction */, 0, 51, 0, 51, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getFunctionName = { { 1888 /* getFunctionName */, 0, 52, 0, 52, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getNamespace = { { 1904 /* getNamespace */, 0, 53, 0, 53, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getParentScope = { { 1917 /* getParentScope */, 0, 54, 0, 54, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig canAnyVariableExist = { { 1932 /* canAnyVariableExist */, 0, 55, 0, 55, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig afterExtractCall = { { 1232 /* afterExtractCall */, 0, 56, 0, 56, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig afterClearstatcacheCall = { { 1952 /* afterClearstatcacheCall */, 0, 57, 0, 57, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig afterOpenSslCall = { { 1996 /* afterOpenSslCall */, 1, 58, 1, 59, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig invalidateVolatileExpressions = { { 2013 /* invalidateVolatileExpressions */, 0, 60, 0, 60, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig invalidateExistenceCheckExpressions = { { 2076 /* invalidateExistenceCheckExpressions */, 2, 61, 2, 63, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig hasVariableType = { { 2146 /* hasVariableType */, 1, 64, 1, 65, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getVariableType = { { 2180 /* getVariableType */, 1, 66, 1, 67, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getDefinedVariables = { { 2196 /* getDefinedVariables */, 0, 68, 0, 68, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getMaybeDefinedVariables = { { 2216 /* getMaybeDefinedVariables */, 0, 69, 0, 69, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig findPossiblyImpureCallDescriptions = { { 2261 /* findPossiblyImpureCallDescriptions */, 1, 70, 1, 71, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig isGlobalVariable = { { 2296 /* isGlobalVariable */, 1, 72, 1, 73, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig hasConstant = { { 2338 /* hasConstant */, 1, 74, 1, 75, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig fileHasCompilerHaltStatementCalls = { { 2350 /* fileHasCompilerHaltStatementCalls */, 0, 76, 0, 76, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig isInAnonymousFunction = { { 2384 /* isInAnonymousFunction */, 0, 77, 0, 77, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getAnonymousFunctionReflection = { { 2406 /* getAnonymousFunctionReflection */, 0, 78, 0, 78, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getAnonymousFunctionReturnType = { { 2437 /* getAnonymousFunctionReturnType */, 0, 79, 0, 79, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig withAnonymousFunctionReflection = { { 2468 /* withAnonymousFunctionReflection */, 1, 80, 1, 81, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getType = { { 2505 /* getType */, 1, 82, 1, 83, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getScopeType = { { 2513 /* getScopeType */, 1, 84, 1, 85, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getScopeNativeType = { { 2526 /* getScopeNativeType */, 1, 86, 1, 87, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getNodeKey = { { 2545 /* getNodeKey */, 1, 88, 1, 89, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getExprPrinter = { { 2556 /* getExprPrinter */, 0, 90, 0, 90, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig duplicateWith = { { 2571 /* duplicateWith */, 8, 91, 8, 99, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getClosureScopeCacheKey = { { 2599 /* getClosureScopeCacheKey */, 0, 100, 1, 101, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig exprStringIsRootedIn = { { 2640 /* exprStringIsRootedIn */, 2, 102, 2, 104, ZEND_ACC_PRIVATE | ZEND_ACC_STATIC } }; -inline constexpr sigtab::Sig resolveType = { { 2661 /* resolveType */, 2, 105, 2, 107, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig resolveTypeOfNewWorldHandlerNode = { { 2673 /* resolveTypeOfNewWorldHandlerNode */, 1, 108, 1, 109, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig getCurrentTypesOfSpecifiedExpr = { { 2706 /* getCurrentTypesOfSpecifiedExpr */, 1, 110, 1, 111, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig specifyTypesOfNewWorldHandlerNode = { { 2807 /* specifyTypesOfNewWorldHandlerNode */, 2, 112, 2, 114, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig obtainResultForNode = { { 2875 /* obtainResultForNode */, 1, 115, 1, 116, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig pushExpressionResultStorage = { { 2944 /* pushExpressionResultStorage */, 1, 117, 1, 118, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig popExpressionResultStorage = { { 2972 /* popExpressionResultStorage */, 0, 119, 0, 119, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig findSettledStoredResult = { { 2999 /* findSettledStoredResult */, 1, 120, 1, 121, ZEND_ACC_PROTECTED } }; -inline constexpr sigtab::Sig getCurrentExpressionResultStorage = { { 3023 /* getCurrentExpressionResultStorage */, 0, 122, 0, 122, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig withTemplateArgumentFrame = { { 3063 /* withTemplateArgumentFrame */, 1, 123, 1, 124, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getCurrentTemplateArgumentFrame = { { 3089 /* getCurrentTemplateArgumentFrame */, 0, 125, 0, 125, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getTemplateArgumentConstraints = { { 3121 /* getTemplateArgumentConstraints */, 0, 126, 0, 126, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig withTemplateArgumentConstraints = { { 3164 /* withTemplateArgumentConstraints */, 1, 127, 1, 128, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig addTemplateArgumentConstraints = { { 3196 /* addTemplateArgumentConstraints */, 1, 129, 1, 130, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig withoutMemoizedTypes = { { 3227 /* withoutMemoizedTypes */, 0, 131, 0, 131, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getDifferingVariableRoots = { { 3254 /* getDifferingVariableRoots */, 1, 132, 1, 133, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getVariablesOfExpressionKey = { { 3284 /* getVariablesOfExpressionKey */, 1, 134, 1, 135, ZEND_ACC_PRIVATE | ZEND_ACC_STATIC } }; -inline constexpr sigtab::Sig withRecordedStatementDelta = { { 3339 /* withRecordedStatementDelta */, 2, 136, 2, 138, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig applyRecordedHolderDelta = { { 3374 /* applyRecordedHolderDelta */, 3, 139, 3, 142, ZEND_ACC_PRIVATE | ZEND_ACC_STATIC } }; -inline constexpr sigtab::Sig getNativeType = { { 3399 /* getNativeType */, 1, 143, 1, 144, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getKeepVoidType = { { 3413 /* getKeepVoidType */, 1, 145, 1, 146, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig doNotTreatPhpDocTypesAsCertain = { { 3429 /* doNotTreatPhpDocTypesAsCertain */, 0, 147, 0, 147, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig promoteNativeTypes = { { 3460 /* promoteNativeTypes */, 0, 148, 0, 148, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig resolveName = { { 3479 /* resolveName */, 1, 149, 1, 150, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig resolveTypeByName = { { 3522 /* resolveTypeByName */, 1, 151, 1, 152, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getTypeFromValue = { { 3546 /* getTypeFromValue */, 1, 153, 1, 154, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig hasExpressionType = { { 3563 /* hasExpressionType */, 1, 155, 1, 156, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getTrackedExpressionType = { { 3581 /* getTrackedExpressionType */, 1, 157, 1, 158, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig pushInFunctionCall = { { 3680 /* pushInFunctionCall */, 3, 159, 3, 162, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig popInFunctionCall = { { 3699 /* popInFunctionCall */, 0, 163, 0, 163, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig isInClassExists = { { 3727 /* isInClassExists */, 1, 164, 1, 165, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getFunctionCallStack = { { 3743 /* getFunctionCallStack */, 0, 166, 0, 166, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getFunctionCallStackWithParameters = { { 3764 /* getFunctionCallStackWithParameters */, 0, 167, 0, 167, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig isInFunctionExists = { { 3812 /* isInFunctionExists */, 1, 168, 1, 169, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig enterClass = { { 3847 /* enterClass */, 1, 170, 1, 171, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig enterTrait = { { 3874 /* enterTrait */, 1, 172, 1, 173, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig enterClassMethod = { { 4418 /* enterClassMethod */, 9, 174, 21, 195, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig enterPropertyHook = { { 4596 /* enterPropertyHook */, 10, 196, 11, 207, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig transformStaticType = { { 4619 /* transformStaticType */, 1, 208, 1, 209, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig getRealParameterTypes = { { 4680 /* getRealParameterTypes */, 1, 210, 1, 211, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig getRealParameterDefaultValues = { { 4702 /* getRealParameterDefaultValues */, 1, 212, 1, 213, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig getParameterAttributes = { { 4822 /* getParameterAttributes */, 1, 214, 1, 215, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig enterFunction = { { 4948 /* enterFunction */, 8, 216, 17, 233, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig enterFunctionLike = { { 5006 /* enterFunctionLike */, 2, 234, 2, 236, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig enterNamespace = { { 5038 /* enterNamespace */, 1, 237, 1, 238, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig enterClosureBind = { { 5090 /* enterClosureBind */, 3, 239, 3, 242, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig restoreOriginalScopeAfterClosureBind = { { 5121 /* restoreOriginalScopeAfterClosureBind */, 1, 243, 1, 244, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig restoreThis = { { 5175 /* restoreThis */, 1, 245, 1, 246, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig enterClosureCall = { { 5187 /* enterClosureCall */, 2, 247, 2, 249, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig isInClosureBind = { { 5204 /* isInClosureBind */, 0, 250, 0, 250, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig withClosureBindScopeClasses = { { 5220 /* withClosureBindScopeClasses */, 1, 251, 1, 252, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig enterAnonymousFunction = { { 5328 /* enterAnonymousFunction */, 2, 253, 3, 256, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig enterAnonymousFunctionWithoutReflection = { { 5351 /* enterAnonymousFunctionWithoutReflection */, 3, 257, 3, 260, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig expressionTypeIsUnchangeable = { { 5440 /* expressionTypeIsUnchangeable */, 1, 261, 1, 262, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig invalidateStaticExpressions = { { 5469 /* invalidateStaticExpressions */, 1, 263, 1, 264, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig enterArrowFunction = { { 5545 /* enterArrowFunction */, 2, 265, 3, 268, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig enterArrowFunctionWithoutReflection = { { 5564 /* enterArrowFunctionWithoutReflection */, 3, 269, 3, 272, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig isParameterValueNullable = { { 5621 /* isParameterValueNullable */, 1, 273, 1, 274, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getFunctionType = { { 5668 /* getFunctionType */, 3, 275, 3, 278, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getCallableParameterType = { { 5690 /* getCallableParameterType */, 3, 279, 3, 282, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig buildVariadicArrayTypeFromCallableParameters = { { 5726 /* buildVariadicArrayTypeFromCallableParameters */, 2, 283, 2, 285, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig intersectButNotNever = { { 5795 /* intersectButNotNever */, 2, 286, 2, 288, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC } }; -inline constexpr sigtab::Sig enterMatch = { { 5867 /* enterMatch */, 3, 289, 3, 292, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig enterForeach = { { 5948 /* enterForeach */, 7, 293, 7, 300, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig enterForeachKey = { { 5961 /* enterForeachKey */, 5, 301, 5, 306, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig enterCatchType = { { 5987 /* enterCatchType */, 2, 307, 2, 309, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig enterExpressionAssign = { { 6015 /* enterExpressionAssign */, 1, 310, 2, 312, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig exitExpressionAssign = { { 6037 /* exitExpressionAssign */, 1, 313, 1, 314, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig isInExpressionAssign = { { 6058 /* isInExpressionAssign */, 1, 315, 1, 316, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig isInWriteExpressionAssign = { { 6079 /* isInWriteExpressionAssign */, 1, 317, 1, 318, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig setAllowedUndefinedExpression = { { 6105 /* setAllowedUndefinedExpression */, 1, 319, 1, 320, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig unsetAllowedUndefinedExpression = { { 6135 /* unsetAllowedUndefinedExpression */, 1, 321, 1, 322, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig isUndefinedExpressionAllowed = { { 6167 /* isUndefinedExpressionAllowed */, 1, 323, 1, 324, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig assignVariable = { { 6232 /* assignVariable */, 4, 325, 5, 330, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig overwriteExpression = { { 6247 /* overwriteExpression */, 3, 331, 3, 334, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig resolveIntertwinedAssignedType = { { 6319 /* resolveIntertwinedAssignedType */, 5, 335, 5, 340, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig isDimFetchPathReachable = { { 6393 /* isDimFetchPathReachable */, 2, 341, 2, 343, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig unsetExpression = { { 6417 /* unsetExpression */, 1, 344, 1, 345, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig getStateType = { { 6433 /* getStateType */, 1, 346, 1, 347, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getScopeStateType = { { 6446 /* getScopeStateType */, 1, 348, 1, 349, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig getScopeStateNativeType = { { 6464 /* getScopeStateNativeType */, 1, 350, 1, 351, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig resolveScopeStateType = { { 6488 /* resolveScopeStateType */, 2, 352, 2, 354, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig specifyExpressionType = { { 6510 /* specifyExpressionType */, 4, 355, 4, 359, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig openSpecificationScope = { { 6532 /* openSpecificationScope */, 0, 360, 0, 360, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig isSpecifyExpressionTypeNoop = { { 6555 /* isSpecifyExpressionTypeNoop */, 2, 361, 2, 363, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig specifyExpressionTypeInPlace = { { 6583 /* specifyExpressionTypeInPlace */, 4, 364, 4, 368, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig assignExpression = { { 6612 /* assignExpression */, 3, 369, 3, 372, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig assignInitializedProperty = { { 6643 /* assignInitializedProperty */, 2, 373, 2, 375, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig invalidateExpression = { { 6752 /* invalidateExpression */, 1, 376, 4, 380, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig isPrivatePropertyOfDifferentClass = { { 6773 /* isPrivatePropertyOfDifferentClass */, 2, 381, 2, 383, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig invalidateMethodsOnExpression = { { 6807 /* invalidateMethodsOnExpression */, 1, 384, 1, 385, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig setExpressionCertaintyKeepingType = { { 6837 /* setExpressionCertaintyKeepingType */, 2, 386, 2, 388, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig isComplexUnionType = { { 6871 /* isComplexUnionType */, 1, 389, 1, 390, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig addTypeToExpression = { { 6890 /* addTypeToExpression */, 2, 391, 2, 393, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig removeTypeFromExpression = { { 6923 /* removeTypeFromExpression */, 2, 394, 2, 396, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig filterByTruthyValue = { { 6948 /* filterByTruthyValue */, 1, 397, 1, 398, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig filterByFalseyValue = { { 6968 /* filterByFalseyValue */, 1, 399, 1, 400, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig applySpecifiedTypes = { { 7003 /* applySpecifiedTypes */, 1, 401, 1, 402, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig processConditionalExpressionsAfterSpecifying = { { 7044 /* processConditionalExpressionsAfterSpecifying */, 1, 403, 1, 404, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig getConditionalExpressions = { { 7089 /* getConditionalExpressions */, 0, 405, 0, 405, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig addConditionalExpressions = { { 7144 /* addConditionalExpressions */, 2, 406, 2, 408, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig exitFirstLevelStatements = { { 7170 /* exitFirstLevelStatements */, 0, 409, 0, 409, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig isInFirstLevelStatement = { { 7195 /* isInFirstLevelStatement */, 0, 410, 0, 410, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig mergeWith = { { 7258 /* mergeWith */, 1, 411, 2, 413, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig collectAbsorbedClosures = { { 7280 /* collectAbsorbedClosures */, 2, 414, 2, 416, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig mergeWithVariableState = { { 7304 /* mergeWithVariableState */, 1, 417, 2, 419, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig withoutPreciseClassConstantFetches = { { 7391 /* withoutPreciseClassConstantFetches */, 3, 420, 3, 423, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig preserveVacuousConditionalExpressions = { { 7506 /* preserveVacuousConditionalExpressions */, 3, 424, 3, 427, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig mergeSameGuardConditionalExpressions = { { 7598 /* mergeSameGuardConditionalExpressions */, 3, 428, 3, 431, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig mergeConditionalExpressions = { { 7692 /* mergeConditionalExpressions */, 2, 432, 2, 434, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig mergeInitializedProperties = { { 7738 /* mergeInitializedProperties */, 1, 435, 1, 436, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig processFinallyScope = { { 7799 /* processFinallyScope */, 2, 437, 2, 439, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig processFinallyScopeVariableTypeHolders = { { 7897 /* processFinallyScopeVariableTypeHolders */, 3, 440, 3, 443, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig processClosureScope = { { 7969 /* processClosureScope */, 3, 444, 3, 447, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig processAlwaysIterableForeachScopeWithoutPollute = { { 8000 /* processAlwaysIterableForeachScopeWithoutPollute */, 1, 448, 1, 449, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig generalizeWith = { { 8070 /* generalizeWith */, 1, 450, 2, 452, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig generalizeWithVariableState = { { 8085 /* generalizeWithVariableState */, 2, 453, 2, 455, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig generalizeVariableTypeHolders = { { 8158 /* generalizeVariableTypeHolders */, 3, 456, 3, 459, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig flattenUnionForGeneralization = { { 8188 /* flattenUnionForGeneralization */, 1, 460, 1, 461, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig generalizeType = { { 8228 /* generalizeType */, 3, 462, 3, 465, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig getArrayDepth = { { 8243 /* getArrayDepth */, 1, 466, 1, 467, ZEND_ACC_PRIVATE | ZEND_ACC_STATIC } }; -inline constexpr sigtab::Sig equals = { { 8257 /* equals */, 1, 468, 1, 469, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig compareConditionalExpressions = { { 8292 /* compareConditionalExpressions */, 2, 470, 2, 472, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig compareVariableTypeHolders = { { 8322 /* compareVariableTypeHolders */, 2, 473, 2, 475, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig canAccessProperty = { { 8406 /* canAccessProperty */, 1, 476, 1, 477, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig canReadProperty = { { 8470 /* canReadProperty */, 1, 478, 1, 479, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig canWriteProperty = { { 8486 /* canWriteProperty */, 1, 480, 1, 481, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig canCallMethod = { { 8556 /* canCallMethod */, 1, 482, 1, 483, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig canAccessConstant = { { 8632 /* canAccessConstant */, 1, 484, 1, 485, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig canAccessClassMember = { { 8713 /* canAccessClassMember */, 1, 486, 1, 487, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig debug = { { 8734 /* debug */, 0, 488, 0, 488, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig filterTypeWithMethod = { { 8766 /* filterTypeWithMethod */, 2, 489, 2, 491, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getMethodReflection = { { 8831 /* getMethodReflection */, 2, 492, 2, 494, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getNakedMethod = { { 8851 /* getNakedMethod */, 2, 495, 2, 497, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getPropertyReflection = { { 8883 /* getPropertyReflection */, 2, 498, 2, 500, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getInstancePropertyReflection = { { 8905 /* getInstancePropertyReflection */, 2, 501, 2, 503, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getStaticPropertyReflection = { { 8935 /* getStaticPropertyReflection */, 2, 504, 2, 506, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getConstantReflection = { { 8993 /* getConstantReflection */, 2, 507, 2, 509, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getConstantExplicitTypeFromConfig = { { 9028 /* getConstantExplicitTypeFromConfig */, 2, 510, 2, 512, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getConstantTypes = { { 9062 /* getConstantTypes */, 0, 513, 0, 513, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig getGlobalConstantType = { { 9079 /* getGlobalConstantType */, 1, 514, 1, 515, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig createGlobalConstantFetches = { { 9112 /* createGlobalConstantFetches */, 3, 516, 3, 519, ZEND_ACC_PRIVATE | ZEND_ACC_STATIC } }; -inline constexpr sigtab::Sig getNativeConstantTypes = { { 9140 /* getNativeConstantTypes */, 0, 520, 0, 520, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig getIterableKeyType = { { 9163 /* getIterableKeyType */, 1, 521, 1, 522, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getIterableValueType = { { 9182 /* getIterableValueType */, 1, 523, 1, 524, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig getPhpVersion = { { 9227 /* getPhpVersion */, 0, 525, 0, 525, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig isOverallPhpVersionRange = { { 9241 /* isOverallPhpVersionRange */, 1, 526, 1, 527, ZEND_ACC_PRIVATE } }; -inline constexpr sigtab::Sig invokeNodeCallback = { { 9281 /* invokeNodeCallback */, 1, 528, 1, 529, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig emitCollectedData = { { 9319 /* emitCollectedData */, 2, 530, 2, 532, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig trackValueDependency = { { 9352 /* trackValueDependency */, 2, 533, 2, 535, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig trackFileDependency = { { 9378 /* trackFileDependency */, 1, 536, 1, 537, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig trackDirectoryDependency = { { 9420 /* trackDirectoryDependency */, 1, 538, 2, 540, ZEND_ACC_PUBLIC } }; -inline constexpr sigtab::Sig trackClassDependency = { { 9445 /* trackClassDependency */, 1, 541, 1, 542, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig __construct = { { 726 /* __construct */, 3, 0, 20, reg::NoArg, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig toNodeCallbackScope = { { 739 /* toNodeCallbackScope */, 0, 20, 0, 20, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig toWalkScope = { { 759 /* toWalkScope */, 0, 21, 0, 21, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig toMutatingScope = { { 771 /* toMutatingScope */, 0, 22, 0, 22, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getFile = { { 787 /* getFile */, 0, 23, 0, 23, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getFileDescription = { { 795 /* getFileDescription */, 0, 24, 0, 24, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig isDeclareStrictTypes = { { 814 /* isDeclareStrictTypes */, 0, 25, 0, 25, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig enterDeclareStrictTypes = { { 835 /* enterDeclareStrictTypes */, 0, 26, 0, 26, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig rememberConstructorExpressions = { { 882 /* rememberConstructorExpressions */, 1, 27, 1, 28, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig classHasCustomSerialization = { { 913 /* classHasCustomSerialization */, 0, 29, 0, 29, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig rememberConstructorScope = { { 941 /* rememberConstructorScope */, 0, 30, 0, 30, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig isReadonlyPropertyFetch = { { 1021 /* isReadonlyPropertyFetch */, 2, 31, 2, 33, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig isInClass = { { 1045 /* isInClass */, 0, 34, 0, 34, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig isInTrait = { { 1055 /* isInTrait */, 0, 35, 0, 35, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getClassReflection = { { 1100 /* getClassReflection */, 0, 36, 0, 36, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getTraitReflection = { { 1119 /* getTraitReflection */, 0, 37, 0, 37, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getFunction = { { 1138 /* getFunction */, 0, 38, 0, 38, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getFunctionName = { { 1150 /* getFunctionName */, 0, 39, 0, 39, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getNamespace = { { 1166 /* getNamespace */, 0, 40, 0, 40, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getParentScope = { { 1179 /* getParentScope */, 0, 41, 0, 41, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig canAnyVariableExist = { { 1194 /* canAnyVariableExist */, 0, 42, 0, 42, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig afterExtractCall = { { 494 /* afterExtractCall */, 0, 43, 0, 43, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig afterClearstatcacheCall = { { 1214 /* afterClearstatcacheCall */, 0, 44, 0, 44, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig afterOpenSslCall = { { 1258 /* afterOpenSslCall */, 1, 45, 1, 46, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig invalidateVolatileExpressions = { { 1275 /* invalidateVolatileExpressions */, 0, 47, 0, 47, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig invalidateExistenceCheckExpressions = { { 1338 /* invalidateExistenceCheckExpressions */, 2, 48, 2, 50, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig hasVariableType = { { 1408 /* hasVariableType */, 1, 51, 1, 52, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getVariableType = { { 1442 /* getVariableType */, 1, 53, 1, 54, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getDefinedVariables = { { 1458 /* getDefinedVariables */, 0, 55, 0, 55, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getMaybeDefinedVariables = { { 1478 /* getMaybeDefinedVariables */, 0, 56, 0, 56, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig findPossiblyImpureCallDescriptions = { { 1523 /* findPossiblyImpureCallDescriptions */, 1, 57, 1, 58, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig isGlobalVariable = { { 1558 /* isGlobalVariable */, 1, 59, 1, 60, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig hasConstant = { { 1600 /* hasConstant */, 1, 61, 1, 62, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig fileHasCompilerHaltStatementCalls = { { 1612 /* fileHasCompilerHaltStatementCalls */, 0, 63, 0, 63, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig isInAnonymousFunction = { { 1646 /* isInAnonymousFunction */, 0, 64, 0, 64, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getAnonymousFunctionReflection = { { 1668 /* getAnonymousFunctionReflection */, 0, 65, 0, 65, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getAnonymousFunctionReturnType = { { 1699 /* getAnonymousFunctionReturnType */, 0, 66, 0, 66, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig withAnonymousFunctionReflection = { { 1730 /* withAnonymousFunctionReflection */, 1, 67, 1, 68, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getType = { { 1767 /* getType */, 1, 69, 1, 70, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getScopeType = { { 1775 /* getScopeType */, 1, 71, 1, 72, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getScopeNativeType = { { 1788 /* getScopeNativeType */, 1, 73, 1, 74, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getNodeKey = { { 1807 /* getNodeKey */, 1, 75, 1, 76, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getExprPrinter = { { 1851 /* getExprPrinter */, 0, 77, 0, 77, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig duplicateWith = { { 1866 /* duplicateWith */, 8, 78, 8, 86, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getClosureScopeCacheKey = { { 1894 /* getClosureScopeCacheKey */, 0, 87, 1, 88, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig exprStringIsRootedIn = { { 1935 /* exprStringIsRootedIn */, 2, 89, 2, 91, ZEND_ACC_PRIVATE | ZEND_ACC_STATIC } }; +inline constexpr sigtab::Sig resolveType = { { 1956 /* resolveType */, 2, 92, 2, 94, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig resolveTypeOfNewWorldHandlerNode = { { 1968 /* resolveTypeOfNewWorldHandlerNode */, 1, 95, 1, 96, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig getCurrentTypesOfSpecifiedExpr = { { 2001 /* getCurrentTypesOfSpecifiedExpr */, 1, 97, 1, 98, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig specifyTypesOfNewWorldHandlerNode = { { 2102 /* specifyTypesOfNewWorldHandlerNode */, 2, 99, 2, 101, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig obtainResultForNode = { { 2170 /* obtainResultForNode */, 1, 102, 1, 103, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig pushExpressionResultStorage = { { 2239 /* pushExpressionResultStorage */, 1, 104, 1, 105, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig popExpressionResultStorage = { { 2267 /* popExpressionResultStorage */, 0, 106, 0, 106, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig findSettledStoredResult = { { 2294 /* findSettledStoredResult */, 1, 107, 1, 108, ZEND_ACC_PROTECTED } }; +inline constexpr sigtab::Sig getCurrentExpressionResultStorage = { { 2318 /* getCurrentExpressionResultStorage */, 0, 109, 0, 109, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig withTemplateArgumentFrame = { { 2358 /* withTemplateArgumentFrame */, 1, 110, 1, 111, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getCurrentTemplateArgumentFrame = { { 2384 /* getCurrentTemplateArgumentFrame */, 0, 112, 0, 112, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getTemplateArgumentConstraints = { { 2416 /* getTemplateArgumentConstraints */, 0, 113, 0, 113, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig withTemplateArgumentConstraints = { { 2459 /* withTemplateArgumentConstraints */, 1, 114, 1, 115, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig addTemplateArgumentConstraints = { { 2491 /* addTemplateArgumentConstraints */, 1, 116, 1, 117, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig withoutMemoizedTypes = { { 2522 /* withoutMemoizedTypes */, 0, 118, 0, 118, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getDifferingVariableRoots = { { 2549 /* getDifferingVariableRoots */, 1, 119, 1, 120, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getVariablesOfExpressionKey = { { 2579 /* getVariablesOfExpressionKey */, 1, 121, 1, 122, ZEND_ACC_PRIVATE | ZEND_ACC_STATIC } }; +inline constexpr sigtab::Sig withRecordedStatementDelta = { { 2634 /* withRecordedStatementDelta */, 2, 123, 2, 125, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig applyRecordedHolderDelta = { { 2669 /* applyRecordedHolderDelta */, 3, 126, 3, 129, ZEND_ACC_PRIVATE | ZEND_ACC_STATIC } }; +inline constexpr sigtab::Sig getNativeType = { { 2694 /* getNativeType */, 1, 130, 1, 131, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getKeepVoidType = { { 2708 /* getKeepVoidType */, 1, 132, 1, 133, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig doNotTreatPhpDocTypesAsCertain = { { 2724 /* doNotTreatPhpDocTypesAsCertain */, 0, 134, 0, 134, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig promoteNativeTypes = { { 2755 /* promoteNativeTypes */, 0, 135, 0, 135, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig resolveName = { { 2774 /* resolveName */, 1, 136, 1, 137, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig resolveTypeByName = { { 2817 /* resolveTypeByName */, 1, 138, 1, 139, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getTypeFromValue = { { 2841 /* getTypeFromValue */, 1, 140, 1, 141, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig hasExpressionType = { { 2858 /* hasExpressionType */, 1, 142, 1, 143, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getTrackedExpressionType = { { 2876 /* getTrackedExpressionType */, 1, 144, 1, 145, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig pushInFunctionCall = { { 2975 /* pushInFunctionCall */, 3, 146, 3, 149, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig popInFunctionCall = { { 2994 /* popInFunctionCall */, 0, 150, 0, 150, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig isInClassExists = { { 3022 /* isInClassExists */, 1, 151, 1, 152, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getFunctionCallStack = { { 3038 /* getFunctionCallStack */, 0, 153, 0, 153, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getFunctionCallStackWithParameters = { { 3059 /* getFunctionCallStackWithParameters */, 0, 154, 0, 154, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig isInFunctionExists = { { 3107 /* isInFunctionExists */, 1, 155, 1, 156, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig enterClass = { { 3142 /* enterClass */, 1, 157, 1, 158, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig enterTrait = { { 3169 /* enterTrait */, 1, 159, 1, 160, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig enterClassMethod = { { 3713 /* enterClassMethod */, 9, 161, 21, 182, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig enterPropertyHook = { { 3891 /* enterPropertyHook */, 10, 183, 11, 194, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig transformStaticType = { { 3914 /* transformStaticType */, 1, 195, 1, 196, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig getRealParameterTypes = { { 3975 /* getRealParameterTypes */, 1, 197, 1, 198, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig getRealParameterDefaultValues = { { 3997 /* getRealParameterDefaultValues */, 1, 199, 1, 200, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig getParameterAttributes = { { 4117 /* getParameterAttributes */, 1, 201, 1, 202, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig enterFunction = { { 4243 /* enterFunction */, 8, 203, 17, 220, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig enterFunctionLike = { { 4301 /* enterFunctionLike */, 2, 221, 2, 223, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig enterNamespace = { { 4333 /* enterNamespace */, 1, 224, 1, 225, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig enterClosureBind = { { 4385 /* enterClosureBind */, 3, 226, 3, 229, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig restoreOriginalScopeAfterClosureBind = { { 4416 /* restoreOriginalScopeAfterClosureBind */, 1, 230, 1, 231, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig restoreThis = { { 4470 /* restoreThis */, 1, 232, 1, 233, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig enterClosureCall = { { 4482 /* enterClosureCall */, 2, 234, 2, 236, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig isInClosureBind = { { 4499 /* isInClosureBind */, 0, 237, 0, 237, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig withClosureBindScopeClasses = { { 4515 /* withClosureBindScopeClasses */, 1, 238, 1, 239, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig enterAnonymousFunction = { { 4623 /* enterAnonymousFunction */, 2, 240, 3, 243, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig enterAnonymousFunctionWithoutReflection = { { 4646 /* enterAnonymousFunctionWithoutReflection */, 3, 244, 3, 247, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig expressionTypeIsUnchangeable = { { 4735 /* expressionTypeIsUnchangeable */, 1, 248, 1, 249, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig invalidateStaticExpressions = { { 4764 /* invalidateStaticExpressions */, 1, 250, 1, 251, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig enterArrowFunction = { { 4840 /* enterArrowFunction */, 2, 252, 3, 255, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig enterArrowFunctionWithoutReflection = { { 4859 /* enterArrowFunctionWithoutReflection */, 3, 256, 3, 259, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig isParameterValueNullable = { { 4916 /* isParameterValueNullable */, 1, 260, 1, 261, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getFunctionType = { { 4963 /* getFunctionType */, 3, 262, 3, 265, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getCallableParameterType = { { 4985 /* getCallableParameterType */, 3, 266, 3, 269, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig buildVariadicArrayTypeFromCallableParameters = { { 5021 /* buildVariadicArrayTypeFromCallableParameters */, 2, 270, 2, 272, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig intersectButNotNever = { { 5090 /* intersectButNotNever */, 2, 273, 2, 275, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC } }; +inline constexpr sigtab::Sig enterMatch = { { 5162 /* enterMatch */, 3, 276, 3, 279, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig enterForeach = { { 5243 /* enterForeach */, 7, 280, 7, 287, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig enterForeachKey = { { 5256 /* enterForeachKey */, 5, 288, 5, 293, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig enterCatchType = { { 5282 /* enterCatchType */, 2, 294, 2, 296, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig enterExpressionAssign = { { 5310 /* enterExpressionAssign */, 1, 297, 2, 299, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig exitExpressionAssign = { { 5332 /* exitExpressionAssign */, 1, 300, 1, 301, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig isInExpressionAssign = { { 5353 /* isInExpressionAssign */, 1, 302, 1, 303, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig isInWriteExpressionAssign = { { 5374 /* isInWriteExpressionAssign */, 1, 304, 1, 305, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig setAllowedUndefinedExpression = { { 5400 /* setAllowedUndefinedExpression */, 1, 306, 1, 307, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig unsetAllowedUndefinedExpression = { { 5430 /* unsetAllowedUndefinedExpression */, 1, 308, 1, 309, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig isUndefinedExpressionAllowed = { { 5462 /* isUndefinedExpressionAllowed */, 1, 310, 1, 311, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig assignVariable = { { 5527 /* assignVariable */, 4, 312, 5, 317, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig overwriteExpression = { { 5542 /* overwriteExpression */, 3, 318, 3, 321, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig resolveIntertwinedAssignedType = { { 5614 /* resolveIntertwinedAssignedType */, 5, 322, 5, 327, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig isDimFetchPathReachable = { { 5688 /* isDimFetchPathReachable */, 2, 328, 2, 330, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig unsetExpression = { { 5712 /* unsetExpression */, 1, 331, 1, 332, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig getStateType = { { 5728 /* getStateType */, 1, 333, 1, 334, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getScopeStateType = { { 5741 /* getScopeStateType */, 1, 335, 1, 336, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig getScopeStateNativeType = { { 5759 /* getScopeStateNativeType */, 1, 337, 1, 338, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig resolveScopeStateType = { { 5783 /* resolveScopeStateType */, 2, 339, 2, 341, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig specifyExpressionType = { { 5805 /* specifyExpressionType */, 4, 342, 4, 346, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig openSpecificationScope = { { 5827 /* openSpecificationScope */, 0, 347, 0, 347, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig isSpecifyExpressionTypeNoop = { { 5850 /* isSpecifyExpressionTypeNoop */, 2, 348, 2, 350, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig specifyExpressionTypeInPlace = { { 5878 /* specifyExpressionTypeInPlace */, 4, 351, 4, 355, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig assignExpression = { { 5907 /* assignExpression */, 3, 356, 3, 359, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig assignInitializedProperty = { { 5938 /* assignInitializedProperty */, 2, 360, 2, 362, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig invalidateExpression = { { 6047 /* invalidateExpression */, 1, 363, 4, 367, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig isPrivatePropertyOfDifferentClass = { { 6068 /* isPrivatePropertyOfDifferentClass */, 2, 368, 2, 370, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig invalidateMethodsOnExpression = { { 6102 /* invalidateMethodsOnExpression */, 1, 371, 1, 372, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig setExpressionCertaintyKeepingType = { { 6132 /* setExpressionCertaintyKeepingType */, 2, 373, 2, 375, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig isComplexUnionType = { { 6166 /* isComplexUnionType */, 1, 376, 1, 377, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig addTypeToExpression = { { 6185 /* addTypeToExpression */, 2, 378, 2, 380, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig removeTypeFromExpression = { { 6218 /* removeTypeFromExpression */, 2, 381, 2, 383, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig filterByTruthyValue = { { 6243 /* filterByTruthyValue */, 1, 384, 1, 385, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig filterByFalseyValue = { { 6263 /* filterByFalseyValue */, 1, 386, 1, 387, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig applySpecifiedTypes = { { 6298 /* applySpecifiedTypes */, 1, 388, 1, 389, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig processConditionalExpressionsAfterSpecifying = { { 6339 /* processConditionalExpressionsAfterSpecifying */, 1, 390, 1, 391, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig getConditionalExpressions = { { 6384 /* getConditionalExpressions */, 0, 392, 0, 392, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig addConditionalExpressions = { { 6439 /* addConditionalExpressions */, 2, 393, 2, 395, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig exitFirstLevelStatements = { { 6465 /* exitFirstLevelStatements */, 0, 396, 0, 396, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig isInFirstLevelStatement = { { 6490 /* isInFirstLevelStatement */, 0, 397, 0, 397, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig mergeWith = { { 6553 /* mergeWith */, 1, 398, 2, 400, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig collectAbsorbedClosures = { { 6575 /* collectAbsorbedClosures */, 2, 401, 2, 403, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig mergeWithVariableState = { { 6599 /* mergeWithVariableState */, 1, 404, 2, 406, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig withoutPreciseClassConstantFetches = { { 6686 /* withoutPreciseClassConstantFetches */, 3, 407, 3, 410, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig preserveVacuousConditionalExpressions = { { 6801 /* preserveVacuousConditionalExpressions */, 3, 411, 3, 414, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig mergeSameGuardConditionalExpressions = { { 6893 /* mergeSameGuardConditionalExpressions */, 3, 415, 3, 418, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig mergeConditionalExpressions = { { 6987 /* mergeConditionalExpressions */, 2, 419, 2, 421, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig mergeInitializedProperties = { { 7033 /* mergeInitializedProperties */, 1, 422, 1, 423, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig processFinallyScope = { { 7094 /* processFinallyScope */, 2, 424, 2, 426, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig processFinallyScopeVariableTypeHolders = { { 7192 /* processFinallyScopeVariableTypeHolders */, 3, 427, 3, 430, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig processClosureScope = { { 7264 /* processClosureScope */, 3, 431, 3, 434, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig processAlwaysIterableForeachScopeWithoutPollute = { { 7295 /* processAlwaysIterableForeachScopeWithoutPollute */, 1, 435, 1, 436, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig generalizeWith = { { 7365 /* generalizeWith */, 1, 437, 2, 439, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig generalizeWithVariableState = { { 7380 /* generalizeWithVariableState */, 2, 440, 2, 442, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig generalizeVariableTypeHolders = { { 7453 /* generalizeVariableTypeHolders */, 3, 443, 3, 446, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig flattenUnionForGeneralization = { { 7483 /* flattenUnionForGeneralization */, 1, 447, 1, 448, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig generalizeType = { { 7523 /* generalizeType */, 3, 449, 3, 452, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig getArrayDepth = { { 7538 /* getArrayDepth */, 1, 453, 1, 454, ZEND_ACC_PRIVATE | ZEND_ACC_STATIC } }; +inline constexpr sigtab::Sig equals = { { 7552 /* equals */, 1, 455, 1, 456, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig compareConditionalExpressions = { { 7587 /* compareConditionalExpressions */, 2, 457, 2, 459, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig compareVariableTypeHolders = { { 7617 /* compareVariableTypeHolders */, 2, 460, 2, 462, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig canAccessProperty = { { 7701 /* canAccessProperty */, 1, 463, 1, 464, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig canReadProperty = { { 7765 /* canReadProperty */, 1, 465, 1, 466, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig canWriteProperty = { { 7781 /* canWriteProperty */, 1, 467, 1, 468, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig canCallMethod = { { 7851 /* canCallMethod */, 1, 469, 1, 470, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig canAccessConstant = { { 7927 /* canAccessConstant */, 1, 471, 1, 472, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig canAccessClassMember = { { 8008 /* canAccessClassMember */, 1, 473, 1, 474, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig debug = { { 8029 /* debug */, 0, 475, 0, 475, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig filterTypeWithMethod = { { 8061 /* filterTypeWithMethod */, 2, 476, 2, 478, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getMethodReflection = { { 8126 /* getMethodReflection */, 2, 479, 2, 481, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getNakedMethod = { { 8146 /* getNakedMethod */, 2, 482, 2, 484, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getPropertyReflection = { { 8178 /* getPropertyReflection */, 2, 485, 2, 487, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getInstancePropertyReflection = { { 8200 /* getInstancePropertyReflection */, 2, 488, 2, 490, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getStaticPropertyReflection = { { 8230 /* getStaticPropertyReflection */, 2, 491, 2, 493, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getConstantReflection = { { 8288 /* getConstantReflection */, 2, 494, 2, 496, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getConstantExplicitTypeFromConfig = { { 8323 /* getConstantExplicitTypeFromConfig */, 2, 497, 2, 499, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getConstantTypes = { { 8357 /* getConstantTypes */, 0, 500, 0, 500, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig getGlobalConstantType = { { 8374 /* getGlobalConstantType */, 1, 501, 1, 502, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig createGlobalConstantFetches = { { 8407 /* createGlobalConstantFetches */, 3, 503, 3, 506, ZEND_ACC_PRIVATE | ZEND_ACC_STATIC } }; +inline constexpr sigtab::Sig getNativeConstantTypes = { { 8435 /* getNativeConstantTypes */, 0, 507, 0, 507, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig getIterableKeyType = { { 8458 /* getIterableKeyType */, 1, 508, 1, 509, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getIterableValueType = { { 8477 /* getIterableValueType */, 1, 510, 1, 511, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig getPhpVersion = { { 8522 /* getPhpVersion */, 0, 512, 0, 512, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig isOverallPhpVersionRange = { { 8536 /* isOverallPhpVersionRange */, 1, 513, 1, 514, ZEND_ACC_PRIVATE } }; +inline constexpr sigtab::Sig invokeNodeCallback = { { 8576 /* invokeNodeCallback */, 1, 515, 1, 516, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig emitCollectedData = { { 8614 /* emitCollectedData */, 2, 517, 2, 519, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig trackValueDependency = { { 8647 /* trackValueDependency */, 2, 520, 2, 522, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig trackFileDependency = { { 8673 /* trackFileDependency */, 1, 523, 1, 524, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig trackDirectoryDependency = { { 8715 /* trackDirectoryDependency */, 1, 525, 2, 527, ZEND_ACC_PUBLIC } }; +inline constexpr sigtab::Sig trackClassDependency = { { 8740 /* trackClassDependency */, 1, 528, 1, 529, ZEND_ACC_PUBLIC } }; } // namespace sig } // namespace ptdecl::MutatingScope diff --git a/turbo-ext/src/generated/NodeCallbackScope.h b/turbo-ext/src/generated/NodeCallbackScope.h index fc575e89f2d..5a8723a79d7 100644 --- a/turbo-ext/src/generated/NodeCallbackScope.h +++ b/turbo-ext/src/generated/NodeCallbackScope.h @@ -10,12 +10,12 @@ namespace ptdecl::NodeCallbackScope { /* the OBJ_PROP_NUM slots of the instance properties the class declares (the inherited ones come first) */ namespace slot { -inline constexpr uint32_t truthyValueExprs = 37; -inline constexpr uint32_t falseyValueExprs = 38; -inline constexpr uint32_t walkScope = 39; -inline constexpr uint32_t seededWalkScope = 40; -inline constexpr uint32_t askedTypes = 41; -inline constexpr uint32_t askedNativeTypes = 42; +inline constexpr uint32_t truthyValueExprs = 24; +inline constexpr uint32_t falseyValueExprs = 25; +inline constexpr uint32_t walkScope = 26; +inline constexpr uint32_t seededWalkScope = 27; +inline constexpr uint32_t askedTypes = 28; +inline constexpr uint32_t askedNativeTypes = 29; } // namespace slot inline void declareClass(reg::Class &cls) diff --git a/turbo-ext/src/support.h b/turbo-ext/src/support.h index ad8e48002c5..c6cd41dd68d 100644 --- a/turbo-ext/src/support.h +++ b/turbo-ext/src/support.h @@ -1151,6 +1151,10 @@ extern zend_class_entry *pt_ce_type_utils; extern zend_class_entry *pt_ce_typehint_helper; /* merged from the parallel port branch */ +/* $scope->services->exprPrinter (MutatingScope.cpp); NULL with an Error + * pending, an UNDEF zval when $services is unwritten */ +zval *pt_mutating_scope_expr_printer(zval *scope); + /* facts about what a type contains, remembered on the type object (types * are immutable) — each fact one bit, its "known" bit the next one up * (TypeCombinatorCache.cpp): pt_type_cached_fact() answers 1 / 0, or -1 diff --git a/turbo-ext/tests/scope-family.php b/turbo-ext/tests/scope-family.php index a0fb591f0d5..7fa71a1e8a4 100644 --- a/turbo-ext/tests/scope-family.php +++ b/turbo-ext/tests/scope-family.php @@ -366,7 +366,7 @@ public function className(object $object): string return strtr(get_class($object), $this->classNorm); } - /** The 33 constructor arguments of a scope, by parameter name. */ + /** The constructor arguments of a scope, by parameter name. */ public function constructorArgs(MutatingScope $scope): array { $args = []; @@ -1105,6 +1105,16 @@ public function exprRef(Node\Expr $expr): mixed return $state; }; +// the scope's ScopeServices with another node callback (the services are +// read-only, so a copy replaces them) +$sfWithNodeCallback = static function (object $services, ?callable $nodeCallback): object { + $args = []; + foreach ((new \ReflectionClass($services))->getConstructor()->getParameters() as $parameter) { + $args[$parameter->getName()] = $parameter->getName() === 'nodeCallback' ? $nodeCallback : $services->{$parameter->getName()}; + } + + return new \PHPStan\Analyser\ScopeServices(...$args); +}; $sfRestore = static function (object $scope, array $state): void { $class = new \ReflectionClass($scope); foreach ($state as $name => $value) { @@ -1350,7 +1360,7 @@ public function exprRef(Node\Expr $expr): mixed // ---- the type resolution core, with the walk's storage // (or a fresh one for a hand-built scope) as the analysis in progress - $stack = $args['expressionResultStorageStack']; + $stack = $args['services']->expressionResultStorageStack; $stack->push($sfStorage ?? new \PHPStan\Analyser\ExpressionResultStorage()); try { foreach ($exprs as $i => $expr) { @@ -2087,42 +2097,42 @@ public function exprRef(Node\Expr $expr): mixed 'getIterableValueType(non-iterable union)' => static fn () => $scope->getIterableValueType($scalarUnion), 'getIterableKeyType(array)' => static fn () => $scope->getIterableKeyType($arrayType), 'getIterableValueType(array)' => static fn () => $scope->getIterableValueType($arrayType), - 'node callback' => static function () use ($scope, $sfHarness, $sfProp, $sfRestore) { - $saved = $sfProp($scope, 'nodeCallback'); + 'node callback' => static function () use ($scope, $sfHarness, $sfProp, $sfRestore, $sfWithNodeCallback) { + $saved = $sfProp($scope, 'services'); $seen = []; $callback = static function (\PhpParser\Node $node, object $answerer) use (&$seen, $sfHarness): void { $seen[] = [$sfHarness->className($node), $sfHarness->className($answerer)]; }; try { - $sfRestore($scope, ['nodeCallback' => $callback]); + $sfRestore($scope, ['services' => $sfWithNodeCallback($saved, $callback)]); $scope->invokeNodeCallback(new \PhpParser\Node\Expr\Variable('cb')); $scope->emitCollectedData('ScopeFamily\\SomeCollector', ['x' => 1]); return $seen; } finally { - $sfRestore($scope, ['nodeCallback' => $saved]); + $sfRestore($scope, ['services' => $saved]); } }, - 'invokeNodeCallback(no callback)' => static function () use ($scope, $sfProp, $sfRestore) { - $saved = $sfProp($scope, 'nodeCallback'); + 'invokeNodeCallback(no callback)' => static function () use ($scope, $sfProp, $sfRestore, $sfWithNodeCallback) { + $saved = $sfProp($scope, 'services'); try { - $sfRestore($scope, ['nodeCallback' => null]); + $sfRestore($scope, ['services' => $sfWithNodeCallback($saved, null)]); $scope->invokeNodeCallback(new \PhpParser\Node\Expr\Variable('cb')); return 'no throw'; } finally { - $sfRestore($scope, ['nodeCallback' => $saved]); + $sfRestore($scope, ['services' => $saved]); } }, - 'emitCollectedData(no callback)' => static function () use ($scope, $sfProp, $sfRestore) { - $saved = $sfProp($scope, 'nodeCallback'); + 'emitCollectedData(no callback)' => static function () use ($scope, $sfProp, $sfRestore, $sfWithNodeCallback) { + $saved = $sfProp($scope, 'services'); try { - $sfRestore($scope, ['nodeCallback' => null]); + $sfRestore($scope, ['services' => $sfWithNodeCallback($saved, null)]); $scope->emitCollectedData('ScopeFamily\\SomeCollector', null); return 'no throw'; } finally { - $sfRestore($scope, ['nodeCallback' => $saved]); + $sfRestore($scope, ['services' => $saved]); } }, ]; From 0e198bbc74c92c60e9a140f9417dbe29e6d3f3e4 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Tue, 20 Oct 2026 20:27:55 +0200 Subject: [PATCH 13/13] Bump expected turbo version --- src/Turbo/TurboExtensionEnabler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Turbo/TurboExtensionEnabler.php b/src/Turbo/TurboExtensionEnabler.php index 9e9e8609bea..df5f6d4e5c1 100644 --- a/src/Turbo/TurboExtensionEnabler.php +++ b/src/Turbo/TurboExtensionEnabler.php @@ -34,7 +34,7 @@ final class TurboExtensionEnabler { - public const EXPECTED_EXTENSION_VERSION = '6366ed7'; + public const EXPECTED_EXTENSION_VERSION = 'af6410d'; private static bool $active = false;