1--TEST--
2Coalesce assign (??=): Basic behavior
3--FILE--
4<?php
5
6// Refcounted values
7$foo = "fo";
8$foo .= "o";
9$bar = "ba";
10$bar .= "r";
11
12// Identity function used to track single-evaluation
13function id($arg) {
14    echo "id($arg)\n";
15    return $arg;
16}
17
18echo "Simple variables:\n";
19$a = 123;
20$a ??= 456;
21var_dump($a);
22
23$b = null;
24$b ??= $foo;
25var_dump($b);
26
27$c = $foo;
28$c ??= $bar;
29var_dump($c);
30
31$d ??= $foo;
32var_dump($c);
33
34echo "\nArrays:\n";
35$ary = [];
36$ary["foo"] ??= 123;
37$ary[$foo] ??= $bar;
38$ary[$bar] ??= $foo;
39var_dump($ary);
40
41$ary = [];
42$ary[id($foo)] ??= 123;
43$ary[id($foo)] ??= $bar;
44$ary[id($bar)] ??= $foo;
45var_dump($ary);
46
47echo "\nObjects:\n";
48$obj = new stdClass;
49$obj->foo ??= 123;
50$obj->$foo ??= $bar;
51$obj->$bar ??= $foo;
52var_dump($obj);
53
54$obj = new stdClass;
55$obj->{id($foo)} ??= 123;
56$obj->{id($foo)} ??= $bar;
57$obj->{id($bar)} ??= $foo;
58var_dump($obj);
59
60class Test {
61    public static $foo;
62    public static $bar;
63}
64
65echo "\nStatic props:\n";
66Test::$foo ??= 123;
67Test::$$foo ??= $bar;
68Test::$$bar ??= $foo;
69var_dump(Test::$foo, Test::$bar);
70
71Test::$foo = null;
72Test::$bar = null;
73Test::${id($foo)} ??= 123;
74Test::${id($foo)} ??= $bar;
75Test::${id($bar)} ??= $foo;
76var_dump(Test::$foo, Test::$bar);
77
78?>
79--EXPECT--
80Simple variables:
81int(123)
82string(3) "foo"
83string(3) "foo"
84string(3) "foo"
85
86Arrays:
87array(2) {
88  ["foo"]=>
89  int(123)
90  ["bar"]=>
91  string(3) "foo"
92}
93id(foo)
94id(foo)
95id(bar)
96array(2) {
97  ["foo"]=>
98  int(123)
99  ["bar"]=>
100  string(3) "foo"
101}
102
103Objects:
104object(stdClass)#1 (2) {
105  ["foo"]=>
106  int(123)
107  ["bar"]=>
108  string(3) "foo"
109}
110id(foo)
111id(foo)
112id(bar)
113object(stdClass)#2 (2) {
114  ["foo"]=>
115  int(123)
116  ["bar"]=>
117  string(3) "foo"
118}
119
120Static props:
121int(123)
122string(3) "foo"
123id(foo)
124id(foo)
125id(bar)
126int(123)
127string(3) "foo"
128