Summary
Argument unpacking (f(...$args)) is broken in three distinct ways, one of which is silent wrong
output. VM is unaffected.
Note e08_spread in the corpus passes, so the sweep is currently green on this feature. The cases
below show that pass is shallow.
1. Fixed untyped params — silent wrong output
<?php function s3($a, $b, $c) { return $a+$b+$c; } $p=[1,2,3]; echo s3(...$p), "\n";
No error. The arguments arrive as zero.
2. Fixed typed params — compile failure
<?php function s3(int $a, int $b, int $c): int { return $a+$b+$c; } $p=[1,2,3]; echo s3(...$p), "\n";
zend: 6
aot : Unsupported cast for arg type int64 from __hashtable__*
The message is the tell for both #1 and #2: the hashtable itself is reaching the parameter slot
instead of its elements. Typed params catch it as a cast error; untyped params silently accept it
and produce 0.
3. Variadic — collected $v is not a usable array
<?php function sv(...$v) { echo array_sum($v), "\n"; } $p=[1,2,3]; sv(...$p);
array_sum($v) prints Object. So the variadic pack is not a PHP array.
Why e08_spread passes anyway
<?php function s(...$v){ echo implode(",", $v), "\n"; } $p=[1,2,3]; s(...$p); s(0, ...$p);
That case only ever feeds $v to implode(), which evidently tolerates whatever $v actually is.
Swap in array_sum() — same function, same call, same spread — and it breaks. The corpus case was
added with #23971 and is not wrong to exist; it just does not reach past implode.
Summary of shapes
| shape |
AOT |
| spread → fixed untyped params |
0 — silent wrong output |
| spread → fixed typed params |
compile failure, Unsupported cast … from __hashtable__* |
spread → variadic, array_sum($v) |
Object — pack is not an array |
spread → variadic, implode(",", $v) |
ok (this is e08_spread) |
Deterministic — 0/3 runs matched on each failing shape.
Context
Environment: php-compiler:22.04-dev, PHP 8.2.32, LLVM 9, master 412a8cf79. Reproducers in
build/micro/x/.
Summary
Argument unpacking (
f(...$args)) is broken in three distinct ways, one of which is silent wrongoutput. VM is unaffected.
Note
e08_spreadin the corpus passes, so the sweep is currently green on this feature. The casesbelow show that pass is shallow.
1. Fixed untyped params — silent wrong output
No error. The arguments arrive as zero.
2. Fixed typed params — compile failure
The message is the tell for both #1 and #2: the hashtable itself is reaching the parameter slot
instead of its elements. Typed params catch it as a cast error; untyped params silently accept it
and produce 0.
3. Variadic — collected
$vis not a usable arrayarray_sum($v)printsObject. So the variadic pack is not a PHP array.Why
e08_spreadpasses anywayThat case only ever feeds
$vtoimplode(), which evidently tolerates whatever$vactually is.Swap in
array_sum()— same function, same call, same spread — and it breaks. The corpus case wasadded with #23971 and is not wrong to exist; it just does not reach past
implode.Summary of shapes
0— silent wrong outputUnsupported cast … from __hashtable__*array_sum($v)Object— pack is not an arrayimplode(",", $v)e08_spread)Deterministic — 0/3 runs matched on each failing shape.
Context
Environment:
php-compiler:22.04-dev, PHP 8.2.32, LLVM 9, master412a8cf79. Reproducers inbuild/micro/x/.