Repository navigation
Fix GH-25238: ReflectionProperty::isInitialized() skips lazy init once cached - #25239
Conversation
| if (EXPECTED(!Z_ISUNDEF_P(value))) { | ||
| RETURN_TRUE; | ||
| } |
There was a problem hiding this comment.
Falling through to has_property() on every IS_UNDEF slot regresses the inline cache fast path from #17698 (8af90424055) whenever isInitialized() is called on an uninitialized or unset() property of a normal (non-lazy) object. Unlike getValue() where IS_UNDEF is an exceptional slow path, returning false for uninitialized typed properties is a primary use case of isInitialized() in serializers/validators, so this completely bypasses the cache for all false results on non-lazy objects.
cc @arnaud-lb
There was a problem hiding this comment.
Good catch, fixed in ab0be44. The fast path now returns false directly for UNDEF slots when the object is not lazy, and only lazy objects take the has_property() path.
| $line = $class->newLazyGhost(function (Line $line) use ($label) { | ||
| $line->label = $label; | ||
| }); | ||
| var_dump($property->isInitialized($line)); |
There was a problem hiding this comment.
This only tests newLazyGhost() where the property is initialized inside the callback, and misses newLazyProxy() (both before and after initialization) as well as a lazy object whose initializer leaves the property uninitialized.
There was a problem hiding this comment.
Added in ab0be44: newLazyProxy() before and after initialization, and a ghost whose initializer leaves the property uninitialized. All of them fail without the fix.
|
Thank you @lazerg @prateekbhujel! |
* PHP-8.5: Fix phpGH-25238: ReflectionProperty::isInitialized() skips lazy init once cached (php#25239)
The inline cache fast path in
isInitialized()returned false as soon as the cached slot wasUNDEF. All properties of an uninitialized lazy object areUNDEF, and so are the slots of a lazy proxy, so once the cache was warm, later lazy objects of the same class were reported as uninitialized and never got initialized. The fast path now falls back tohas_property()only when the slot isUNDEFand the object is lazy. Non-lazy objects still get the cached answer.Fixes #25238