1--TEST--
2Lazy objects: property op on skipped property does not initialize object
3--FILE--
4<?php
5
6class C {
7    public $a;
8    public int $b = 1;
9    public int $c;
10    public function __construct() {
11        var_dump(__METHOD__);
12        $this->a = 2;
13    }
14}
15
16function test(string $name, object $obj) {
17    printf("# %s:\n", $name);
18
19    $reflector = new ReflectionClass($obj);
20    $reflector->getProperty('a')->skipLazyInitialization($obj);
21    $reflector->getProperty('b')->skipLazyInitialization($obj);
22    $reflector->getProperty('c')->skipLazyInitialization($obj);
23
24    var_dump($obj);
25    var_dump($obj->a++);
26    var_dump($obj->b++);
27    try {
28        var_dump($obj->c++);
29    } catch (Error $e) {
30        printf("%s\n", $e->getMessage());
31    }
32    var_dump($obj);
33}
34
35$reflector = new ReflectionClass(C::class);
36
37$obj = $reflector->newLazyGhost(function ($obj) {
38    var_dump("initializer");
39    $obj->__construct();
40});
41
42test('Ghost', $obj);
43
44$obj = $reflector->newLazyProxy(function ($obj) {
45    var_dump("initializer");
46    return new c();
47});
48
49test('Proxy', $obj);
50
51--EXPECTF--
52# Ghost:
53object(C)#%d (2) {
54  ["a"]=>
55  NULL
56  ["b"]=>
57  int(1)
58  ["c"]=>
59  uninitialized(int)
60}
61NULL
62int(1)
63Typed property C::$c must not be accessed before initialization
64object(C)#%d (2) {
65  ["a"]=>
66  int(1)
67  ["b"]=>
68  int(2)
69  ["c"]=>
70  uninitialized(int)
71}
72# Proxy:
73object(C)#%d (2) {
74  ["a"]=>
75  NULL
76  ["b"]=>
77  int(1)
78  ["c"]=>
79  uninitialized(int)
80}
81NULL
82int(1)
83Typed property C::$c must not be accessed before initialization
84object(C)#%d (2) {
85  ["a"]=>
86  int(1)
87  ["b"]=>
88  int(2)
89  ["c"]=>
90  uninitialized(int)
91}
92