Skip to content

Commit

Permalink
try to fix "in_array() will always evaluate to true." false positives
Browse files Browse the repository at this point in the history
  • Loading branch information
staabm committed Apr 29, 2024
1 parent 68ea78c commit 74f9968
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 3 deletions.
17 changes: 16 additions & 1 deletion src/Rules/Comparison/ImpossibleCheckTypeHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public function findSpecifiedType(
return null;
} elseif ($functionName === 'array_search') {
return null;
} elseif ($functionName === 'in_array' && $argsCount >= 3) {
} elseif ($functionName === 'in_array' && $argsCount >= 2) {
$haystackArg = $node->getArgs()[1]->value;
$haystackType = ($this->treatPhpDocTypesAsCertain ? $scope->getType($haystackArg) : $scope->getNativeType($haystackArg));
if ($haystackType instanceof MixedType) {
Expand All @@ -101,6 +101,21 @@ public function findSpecifiedType(

$needleArg = $node->getArgs()[0]->value;
$needleType = ($this->treatPhpDocTypesAsCertain ? $scope->getType($needleArg) : $scope->getNativeType($needleArg));

$isStrictComparison = false;
if ($argsCount >= 3) {
$strictNodeType = $scope->getType($node->getArgs()[2]->value);
$isStrictComparison = $strictNodeType->isTrue()->yes();
}

$isStrictComparison = $isStrictComparison
|| $needleType->isEnum()->yes()
|| $haystackType->getIterableValueType()->isEnum()->yes();

if (!$isStrictComparison) {
return null;
}

$valueType = $haystackType->getIterableValueType();
$constantNeedleTypesCount = count($needleType->getFiniteTypes());
$constantHaystackTypesCount = count($valueType->getFiniteTypes());
Expand Down
6 changes: 5 additions & 1 deletion src/Type/Php/InArrayFunctionTypeSpecifyingExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,11 @@ public function specifyTypes(FunctionReflection $functionReflection, FuncCall $n
|| $arrayValueType->isEnum()->yes();

if (!$isStrictComparison) {
if ($context->true() && $arrayType->isArray()->yes() && $arrayType->getIterableValueType()->isSuperTypeOf($needleType)->yes()) {
if (
$context->true()
&& $arrayType->isArray()->yes()
&& $arrayType->getIterableValueType()->isSuperTypeOf($needleType)->yes()
) {
return $this->typeSpecifier->create(
$node->getArgs()[1]->value,
TypeCombinator::intersect($arrayType, new NonEmptyArrayType()),
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3032,7 +3032,7 @@ public function dataBinaryOperations(): array
'is_int($string)',
],
[
'true',
'bool',
'in_array(\'foo\', [\'foo\', \'bar\'])',
],
[
Expand Down

0 comments on commit 74f9968

Please sign in to comment.