parent
456f1a38b2
commit
a4820ff759
2 changed files with 123 additions and 2 deletions
@ -0,0 +1,103 @@ |
||||
--TEST-- |
||||
??= preserves references returned as writable array containers |
||||
--FILE-- |
||||
<?php |
||||
|
||||
function keyName(string $label): string |
||||
{ |
||||
echo "key:$label\n"; |
||||
return 'value'; |
||||
} |
||||
|
||||
function rhs(string $label): int |
||||
{ |
||||
echo "rhs:$label\n"; |
||||
return 42; |
||||
} |
||||
|
||||
function &referencedValues(): array |
||||
{ |
||||
global $values; |
||||
return $values; |
||||
} |
||||
|
||||
function valuesByValue(): array |
||||
{ |
||||
return []; |
||||
} |
||||
|
||||
class ReferenceContainer |
||||
{ |
||||
private array $values = []; |
||||
|
||||
public function &values(): array |
||||
{ |
||||
return $this->values; |
||||
} |
||||
|
||||
public function all(): array |
||||
{ |
||||
return $this->values; |
||||
} |
||||
} |
||||
|
||||
function main(): void |
||||
{ |
||||
global $values; |
||||
|
||||
// A known by-reference function must write through to the global array. |
||||
$values = []; |
||||
referencedValues()[keyName('function-unset')] ??= rhs('function-unset'); |
||||
var_dump($values); |
||||
|
||||
// The set branch still evaluates the key once and keeps the RHS lazy. |
||||
$values = ['value' => 7]; |
||||
var_dump(referencedValues()[keyName('function-set')] ??= rhs('function-set')); |
||||
var_dump($values); |
||||
|
||||
// A dynamic call is resolved only at runtime, so its reference identity |
||||
// must survive the same container stabilization boundary. |
||||
$callback = 'referencedValues'; |
||||
$values = []; |
||||
$callback()[keyName('dynamic')] ??= rhs('dynamic'); |
||||
var_dump($values); |
||||
|
||||
// The conservative dynamic-call path must also accept an ordinary |
||||
// by-value array result as a disposable write target. |
||||
$callback = 'valuesByValue'; |
||||
var_dump($callback()[keyName('dynamic-value')] ??= rhs('dynamic-value')); |
||||
|
||||
// Method return references follow the same write-through rules. |
||||
$container = new ReferenceContainer(); |
||||
$container->values()[keyName('method')] ??= rhs('method'); |
||||
var_dump($container->all()); |
||||
} |
||||
?> |
||||
--EXPECT-- |
||||
key:function-unset |
||||
rhs:function-unset |
||||
array(1) { |
||||
["value"]=> |
||||
int(42) |
||||
} |
||||
key:function-set |
||||
int(7) |
||||
array(1) { |
||||
["value"]=> |
||||
int(7) |
||||
} |
||||
key:dynamic |
||||
rhs:dynamic |
||||
array(1) { |
||||
["value"]=> |
||||
int(42) |
||||
} |
||||
key:dynamic-value |
||||
rhs:dynamic-value |
||||
int(42) |
||||
key:method |
||||
rhs:method |
||||
array(1) { |
||||
["value"]=> |
||||
int(42) |
||||
} |
||||
Loading…
Reference in new issue