Merge pull request #11 from hafung/fix/array-keys-dynamic-strict

Fix dynamic strict flag in optimized array_keys calls
master
韩天峰 14 hours ago committed by GitHub
commit e0c1298798
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 8
      src/Optimizer/FuncCallOptimizer.php
  2. 139
      tests/compiler/stdlib/array-keys-dynamic-arguments.phpt

@ -766,11 +766,15 @@ trait FuncCallOptimizer
return 'php::fn::get_parent_class(' . $this->parseIdentifier($arg) . ')';
}
protected function genArrayKeys(string $n, Node\Expr\FuncCall $e, array $c): string
protected function genArrayKeys(string $n, Node\Expr\FuncCall $e, array $c): string|false
{
$cnt = count($e->args);
if ($cnt >= 3) {
return 'php::fn::array_keys_filter(' . $this->getArg($e, 0) . ', ' . $this->getArg($e, 1) . ', ' . $this->getArg($e, 2) . ')';
if ($this->detectTypeOfExpr($e->args[2]->value) !== Type::BOOL) {
return false;
}
return 'php::fn::array_keys_filter(' . $this->getArg($e, 0) . ', ' . $this->getArg($e, 1) . ', '
. $this->resolveArg($e, 2, self::ARG_TYPE_BOOL) . ')';
}
if ($cnt >= 2) {
return 'php::fn::array_keys_filter(' . $this->getArg($e, 0) . ', ' . $this->getArg($e, 1) . ', false)';

@ -0,0 +1,139 @@
--TEST--
array_keys optimized calls preserve dynamic arguments, strict types, and evaluation order
--FILE--
<?php
declare(strict_types=1);
final class ArrayKeysOptions
{
public bool $strict = true;
}
function arrayKeysDynamicStrict(array &$events): bool
{
$events[] = 'strict';
return true;
}
function arrayKeysDynamicValues(array &$events): array
{
$events[] = 'array';
return ['integer' => 1, 'string' => '1'];
}
function arrayKeysDynamicFilter(array &$events): mixed
{
$events[] = 'filter';
return '1';
}
function arrayKeysMixedBool(): mixed
{
return true;
}
function arrayKeysMixedInt(): mixed
{
return 1;
}
function arrayKeysMixedArray(): mixed
{
return [];
}
function arrayKeysUnionInt(): bool|int
{
return 1;
}
function main()
{
$values = ['integer' => 1, 'string' => '1'];
var_dump(array_keys($values));
var_dump(array_keys($values, '1'));
var_dump(array_keys($values, '1', true));
$strict = true;
var_dump(array_keys($values, '1', $strict));
$options = new ArrayKeysOptions();
var_dump(array_keys($values, '1', $options->strict));
$events = [];
var_dump(array_keys(
arrayKeysDynamicValues($events),
arrayKeysDynamicFilter($events),
arrayKeysDynamicStrict($events)
));
var_dump($events);
var_dump(array_keys($values, '1', arrayKeysMixedBool()));
try {
array_keys($values, '1', arrayKeysMixedInt());
echo "mixed-int=missing TypeError\n";
} catch (TypeError $error) {
echo "mixed-int=TypeError\n";
}
try {
array_keys($values, '1', arrayKeysMixedArray());
echo "mixed-array=missing TypeError\n";
} catch (TypeError $error) {
echo "mixed-array=TypeError\n";
}
try {
array_keys($values, '1', arrayKeysUnionInt());
echo "union-int=missing TypeError\n";
} catch (TypeError $error) {
echo "union-int=TypeError\n";
}
}
?>
--EXPECT--
array(2) {
[0]=>
string(7) "integer"
[1]=>
string(6) "string"
}
array(2) {
[0]=>
string(7) "integer"
[1]=>
string(6) "string"
}
array(1) {
[0]=>
string(6) "string"
}
array(1) {
[0]=>
string(6) "string"
}
array(1) {
[0]=>
string(6) "string"
}
array(1) {
[0]=>
string(6) "string"
}
array(3) {
[0]=>
string(5) "array"
[1]=>
string(6) "filter"
[2]=>
string(6) "strict"
}
array(1) {
[0]=>
string(6) "string"
}
mixed-int=TypeError
mixed-array=TypeError
union-int=TypeError
Loading…
Cancel
Save