Category
language · php-src-strict
Problem
PHP 8.0+ throw expressions work in throwing branches ($x ?? throw ... when $x is null throws), but when the non-throwing branch is taken the expression must return the left-hand value.
Verified locally (2026-06-18):
| Call |
Zend PHP 8.2 |
This compiler VM |
f(1) for return $x ?? throw new Exception("e"); |
int(1) |
empty string / no value (echo f(1) prints x= only) |
f(null) |
throws |
throws (OK) |
Distinct from parse rejection — syntax compiles; runtime lowering of ZEND_AST_THROW in coalesce/ternary contexts loses the RHS value.
php-src reference
Repro
./script/docker-exec.sh -- bash -lc 'source script/php-env.sh
php bin/vm.php -r "
function f(?int \$x): int {
return \$x ?? throw new Exception(\"e\");
}
try {
echo \"null=\", f(null), PHP_EOL;
} catch (Throwable \$e) {
echo \"caught\n\";
}
echo \"one=\", f(1), PHP_EOL;
"'
# Zend: caught / one=1
# VM today: caught / one= (empty)
Scope (this repo)
| Path |
Work |
lib/Compiler.php |
Throw-expression coalesce/ternary lowering |
lib/VM.php |
Opcode execution for coalesce + throw expr |
lib/JIT/ |
Match VM when JIT compiles throw expressions |
Done when
Related
Category
language· php-src-strictProblem
PHP 8.0+
throwexpressions work in throwing branches ($x ?? throw ...when$xis null throws), but when the non-throwing branch is taken the expression must return the left-hand value.Verified locally (2026-06-18):
f(1)forreturn $x ?? throw new Exception("e");int(1)echo f(1)printsx=only)f(null)Distinct from parse rejection — syntax compiles; runtime lowering of
ZEND_AST_THROWin coalesce/ternary contexts loses the RHS value.php-src reference
Zend/zend_compile.c— throw-expression compile nodes in coalesceZend/zend_execute.c—ZEND_COALESCE,ZEND_THROWinteractionZend/tests/throw/throw_as_expression*.phptRepro
Scope (this repo)
lib/Compiler.phplib/VM.phplib/JIT/Done when
caughtthenone=1on VM (and JIT if applicable)Zend/tests/throw/minimal caseRelated