1--TEST--
2__set() should not be invoked when setting an uninitialized typed property
3--FILE--
4<?php
5
6class Test {
7    public int $foo;
8    public function __get($name) {
9        echo "__get ", $name, "\n";
10        return null;
11    }
12    public function __set($name, $value) {
13        echo "__set ", $name, " = ", $value, "\n";
14    }
15    public function __isset($name) {
16        echo "__isset ", $name, "\n";
17        return true;
18    }
19    public function __unset($name) {
20        echo "__unset ", $name, "\n";
21    }
22}
23
24$test = new Test;
25try {
26    var_dump($test->foo);
27} catch (Error $e) {
28    echo $e->getMessage(), "\n";
29}
30var_dump(isset($test->foo));
31$test->foo = 42;
32var_dump($test->foo);
33
34// __set will be called after unset()
35unset($test->foo);
36$test->foo = 42;
37
38// __set will be called after unset() without prior initialization
39$test = new Test;
40unset($test->foo);
41$test->foo = 42;
42
43class Test2 extends Test {
44}
45
46// Check that inherited properties work correctly
47$test = new Test;
48$test->foo = 42;
49var_dump($test->foo);
50unset($test->foo);
51$test->foo = 42;
52
53// Test that cloning works correctly
54$test = clone $test;
55$test->foo = 42;
56$test = clone new Test;
57$test->foo = 42;
58var_dump($test->foo);
59unset($test->foo);
60$test->foo = 42;
61
62?>
63--EXPECT--
64Typed property Test::$foo must not be accessed before initialization
65bool(false)
66int(42)
67__set foo = 42
68__set foo = 42
69int(42)
70__set foo = 42
71__set foo = 42
72int(42)
73__set foo = 42
74