Fix dynamic strict flag in optimized array_keys calls - #11
Conversation
|
CI update: both Linux PHPT jobs (PHP 8.4 and 8.5), both Linux PHPUnit jobs, and all other platform builds passed. The sole red macOS ARM64 / PHP 8.4 job failed before checkout build steps because setup-php could not download Composer from any mirror. macOS ARM64 / PHP 8.5 passed. I attempted to rerun only the failed job, but fork PR permissions do not allow reruns. |
matyhtf
left a comment
There was a problem hiding this comment.
Thanks for the focused fix and the thorough positive coverage. The ABI issue for runtime-backed boolean expressions is real, but this implementation also changes PHP's strict parameter-validation semantics.
resolveArg($e, 2, self::ARG_TYPE_BOOL) eventually applies php::toBool() whenever the expression does not already have a fixed C++ bool representation. That is correct for a typed bool property or typed bool function return represented as php::Var, but it also accepts mixed, int, string, and array expressions.
For example, Zend PHP must throw a TypeError here:
declare(strict_types=1);
function strictFlag(): mixed
{
return 1;
}
array_keys(['integer' => 1], 1, strictFlag());With this patch, the optimized path converts 1 to true and returns normally, bypassing the internal-function argument check. TypePHP only supports strict_types=1, so this coercion is not compatible.
Please restrict the optimized path to expressions whose semantic type is definitely bool. Typed properties and typed function returns should then continue through resolveArg() to normalize their C++ representation. For mixed, unions, or any non-boolean semantic type, genArrayKeys() should return false and use the existing Zend dynamic-call path for runtime validation.
Please also add a negative PHPT proving that a runtime-backed non-boolean third argument still raises TypeError. The current test only covers runtime values that are actually boolean.
The macOS PHP 8.4 failure appears unrelated: setup-php failed while downloading Composer before the project was built.
|
Addressed the strict-type review in d480c5e.
Local verification: focused PHPT PASS through translation/MSVC/link/run/EXPECT; O0 and O3 torture artifacts both exit 0 with all three TypeErrors observed; FunctionTest.php 23 tests/35 assertions; typephp-native-core Zend suite PASS assertions=38. |
Summary
Fix the optimized three-argument
array_keys()path when the$strictflag is a runtime-backed expression.genArrayKeys()passed the parsed third argument directly tophp::fn::array_keys_filter(). Typed property reads and typed user-function returns are represented asphp::Varat that boundary, while the PHPX helper requires a C++bool, so otherwise valid PHP translated successfully but failed during native compilation.The fix routes only the strict flag through the optimizer's shared boolean argument resolver. The one- and two-argument fast paths and the existing array/filter ABI are unchanged.
Semantic invariant
Every valid
array_keys($array, $filter, $strict)call must:booltophp::fn::array_keys_filter();Relevance matrix
array,filter,strict1versus string'1'distinguishes loose and strict matchingVerification
phpunit/src/FunctionTest.php: OK (23 tests, 35 assertions).git diff --check: passed.php::VartoboolC2664 failure at O0 and O3.Generated O0/O3 C++ materializes the three dynamic operands in source order and calls
php::toBool()only for the third operand.The full PHPUnit suite is not claimed: this Windows environment has unrelated existing failures and stops at a Linux-only profiling configuration. PHPStan is also not claimed because the repository's Composer script references a
phpstan.neonfile absent from this checkout. Non-MSVC backends were not run locally.