1--TEST-- 2Lazy objects: setRawValueWithoutLazyInitialization() leaves non-lazy properties as non-lazy in case of exception 3--FILE-- 4<?php 5 6class C { 7 public int $a; 8 public int $b; 9} 10 11function test(string $name, object $obj) { 12 printf("# %s\n", $name); 13 14 $reflector = new ReflectionClass(C::class); 15 $reflector->getProperty('a')->skipLazyInitialization($obj); 16 try { 17 $reflector->getProperty('a')->setRawValueWithoutLazyInitialization($obj, new stdClass); 18 } catch (Error $e) { 19 printf("%s: %s\n", $e::class, $e->getMessage()); 20 } 21 22 // Prop is still non-lazy: This does not trigger initialization 23 $obj->a = 1; 24 var_dump($reflector->isUninitializedLazyObject($obj)); 25 var_dump($obj); 26} 27 28$reflector = new ReflectionClass(C::class); 29$obj = $reflector->newLazyGhost(function ($obj) { 30 throw new Exception('Unreachable'); 31}); 32 33test('Ghost', $obj); 34 35$obj = $reflector->newLazyProxy(function () { 36 throw new Exception('Unreachable'); 37}); 38 39test('Proxy', $obj); 40 41?> 42--EXPECTF-- 43# Ghost 44TypeError: Cannot assign stdClass to property C::$a of type int 45bool(true) 46lazy ghost object(C)#%d (1) { 47 ["a"]=> 48 int(1) 49 ["b"]=> 50 uninitialized(int) 51} 52# Proxy 53TypeError: Cannot assign stdClass to property C::$a of type int 54bool(true) 55lazy proxy object(C)#%d (1) { 56 ["a"]=> 57 int(1) 58 ["b"]=> 59 uninitialized(int) 60} 61