Skip to content

Commit

Permalink
Fix return type of array_search() with constant array type haystack
Browse files Browse the repository at this point in the history
  • Loading branch information
takaram committed Nov 5, 2022
1 parent 7a7b386 commit fe102f9
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 15 deletions.
19 changes: 4 additions & 15 deletions src/Type/Constant/ConstantArrayType.php
Expand Up @@ -743,37 +743,26 @@ public function popArray(): Type
public function searchArray(Type $needleType): Type
{
$matches = [];
$optionalDirectMatches = [];
$hasIdenticalValue = false;

foreach ($this->valueTypes as $index => $valueType) {
$isNeedleSuperType = $valueType->isSuperTypeOf($needleType);
if ($isNeedleSuperType->no()) {
$matches[] = new ConstantBooleanType(false);
continue;
}

if ($needleType instanceof ConstantScalarType && $valueType instanceof ConstantScalarType
&& $needleType->getValue() === $valueType->getValue()
&& !$this->isOptionalKey($index)
) {
if (!$this->isOptionalKey($index)) {
return TypeCombinator::union($this->keyTypes[$index], ...$optionalDirectMatches);
}
$optionalDirectMatches[] = $this->keyTypes[$index];
$hasIdenticalValue = true;
}

$matches[] = $this->keyTypes[$index];
if (!$isNeedleSuperType->maybe()) {
continue;
}

$matches[] = new ConstantBooleanType(false);
}

if (count($matches) > 0) {
if (
$this->getIterableValueType()->accepts($needleType, true)->yes()
&& $needleType->isSuperTypeOf(new ObjectWithoutClassType())->no()
) {
if ($hasIdenticalValue) {
return TypeCombinator::union(...$matches);
}

Expand Down
1 change: 1 addition & 0 deletions tests/PHPStan/Analyser/NodeScopeResolverTest.php
Expand Up @@ -1124,6 +1124,7 @@ public function dataFileAsserts(): iterable
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-8272.php');
yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Comparison/data/bug-8277.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/strtr.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-3789.php');
}

/**
Expand Down
17 changes: 17 additions & 0 deletions tests/PHPStan/Analyser/data/bug-3789.php
@@ -0,0 +1,17 @@
<?php

namespace Bug3789;

use function PHPStan\Testing\assertType;

/**
* @param array{string, string, string} $haystack
*/
function doFoo(string $needle, array $haystack): void {
assertType('0|1|2|false', array_search($needle, $haystack, true));
assertType('0|1|2|false', array_search('foo', $haystack, true));

$haystack[1] = 'foo';
assertType('0|1|2|false', array_search($needle, $haystack, true));
assertType('0|1|2', array_search('foo', $haystack, true));
}

0 comments on commit fe102f9

Please sign in to comment.