[php-src] PR #23434: [skip ci] Document the closure $this internals change in UPGRADING.INTERNALS

From: Date: Mon, 24 Aug 2026 12:10:56 +0000
Subject: [php-src] PR #23434: [skip ci] Document the closure $this internals change in UPGRADING.INTERNALS
Groups: php.git-pulls 
Request: Send a blank email to git-pulls+get-38102@lists.php.net to get a copy of this message
Pull Request: https://github.com/php/php-src/pull/23434 Author: nicolas-grekas zend_create_closure(), zend_create_fake_closure() and zend_create_partial_closure() take the bound $this as a zend_object* since fbb2e1f23d6, and zend_get_closure_this_ptr() returns one — NULL when the closure is unbound, where it used to return a zval* that is IS_UNDEF — since 7a5e452f14c. Neither commit added a note to UPGRADING.INTERNALS, so this adds one to the "Changed" list of section 1, next to the other signature changes. Worth documenting because the change is silent for extension authors: passing a zval* where a zend_object* is now expected is only a -Wincompatible-pointer-types warning, so an extension still builds and then reads the wrong struct at runtime. Concretely, ext-deepclone built clean-looking against master and segfaulted: ``` zend_hash_index_find_bucket (ht=0x7ffff2c87e61, h=757) zim_DeepClone_HydrationContext_hydrate (deepclone.c:4007) zend_call_known_fcc_ex (fcc->object = 0x7ffff2c87eb9) zend_lazy_object_init (zend_lazy_objects.c:661) ``` Its lazy-object initializer was created with zend_create_fake_closure(..., &this_zval); the engine stored that zval* as the closure's this_ptr and handed it back as $this, so Z_OBJ_P(ZEND_THIS) in the initializer dereferenced a zval as an object.

« previous php.git-pulls (#38102) next »