diff --git a/src/Analyser/TypeSpecifier.php b/src/Analyser/TypeSpecifier.php index 4ea8a595f5..1abb42b684 100644 --- a/src/Analyser/TypeSpecifier.php +++ b/src/Analyser/TypeSpecifier.php @@ -663,7 +663,24 @@ public function specifyTypesInCondition( $leftTypes = $this->specifyTypesInCondition($scope, $expr->left, $context)->setRootExpr($expr); $rightScope = $scope->filterByFalseyValue($expr->left); $rightTypes = $this->specifyTypesInCondition($rightScope, $expr->right, $context)->setRootExpr($expr); - $types = $context->true() ? $leftTypes->normalize($scope)->intersectWith($rightTypes->normalize($rightScope)) : $leftTypes->unionWith($rightTypes); + + if ($context->true()) { + if ( + $scope->getType($expr->left)->toBoolean()->isFalse()->yes() + ) { + $types = $rightTypes->normalize($rightScope); + } elseif ( + $scope->getType($expr->left)->toBoolean()->isTrue()->yes() + || $scope->getType($expr->right)->toBoolean()->isFalse()->yes() + ) { + $types = $leftTypes->normalize($scope); + } else { + $types = $leftTypes->normalize($scope)->intersectWith($rightTypes->normalize($rightScope)); + } + } else { + $types = $leftTypes->unionWith($rightTypes); + } + if ($context->true()) { return (new SpecifiedTypes( $types->getSureTypes(), diff --git a/tests/PHPStan/Analyser/TypeSpecifierTest.php b/tests/PHPStan/Analyser/TypeSpecifierTest.php index 9edca89ab9..dfcfae42dc 100644 --- a/tests/PHPStan/Analyser/TypeSpecifierTest.php +++ b/tests/PHPStan/Analyser/TypeSpecifierTest.php @@ -353,7 +353,7 @@ public static function dataCondition(): iterable self::createFunctionCall('is_int', 'foo'), self::createFunctionCall('is_string', 'bar'), ), - [], + ['$foo' => 'int'], ['$foo' => '~int', '$bar' => '~string'], ], [ @@ -652,7 +652,7 @@ public static function dataCondition(): iterable [ new Expr\Empty_(new Variable('array')), [ - '$array' => 'array{}|null', + '$array' => 'array{}', ], [ '$array' => '~0|0.0|\'\'|\'0\'|array{}|false|null', @@ -664,7 +664,7 @@ public static function dataCondition(): iterable '$array' => '~0|0.0|\'\'|\'0\'|array{}|false|null', ], [ - '$array' => 'array{}|null', + '$array' => 'array{}', ], ], [ diff --git a/tests/PHPStan/Analyser/nsrt/bug-11276.php b/tests/PHPStan/Analyser/nsrt/bug-11276.php new file mode 100644 index 0000000000..7104f4da31 --- /dev/null +++ b/tests/PHPStan/Analyser/nsrt/bug-11276.php @@ -0,0 +1,59 @@ += 8.0 + +namespace Bug11276b; + +use function PHPStan\Testing\assertType; + +function doBar($j, array $arr) { + $i = 1; + if (!array_key_exists($i, $arr)) { + if (array_key_exists($i, $arr) || array_key_exists($j, $arr)) { + assertType('non-empty-array', $arr); + } + } + + if (!array_key_exists($i, $arr)) { + if (array_key_exists($j, $arr) || array_key_exists($i, $arr)) { + assertType('non-empty-array', $arr); + } + } +} diff --git a/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php b/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php index 7e6f66d60c..597b4000e3 100644 --- a/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php +++ b/tests/PHPStan/Rules/Arrays/NonexistentOffsetInArrayDimFetchRuleTest.php @@ -1132,4 +1132,10 @@ public function testBug6209(): void $this->analyse([__DIR__ . '/data/bug-6209.php'], []); } + public function testBug11276(): void + { + $this->reportPossiblyNonexistentConstantArrayOffset = true; + $this->analyse([__DIR__ . '/data/bug-11276.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Arrays/data/bug-11276.php b/tests/PHPStan/Rules/Arrays/data/bug-11276.php new file mode 100644 index 0000000000..3a69fbed7c --- /dev/null +++ b/tests/PHPStan/Rules/Arrays/data/bug-11276.php @@ -0,0 +1,26 @@ +[a-z]{2})-(?[a-z]{1}[a-z0-9]{1})\/#', $url, $matches); + + foreach ($expected as $key => $value) { + if ($matches instanceof ArrayAccess || \array_key_exists($key, $matches)) { + $matches[$key]; + } + } + + foreach ($expected as $key => $value) { + if (\array_key_exists($key, $matches) || $matches instanceof ArrayAccess) { + $matches[$key]; + } + } + } +} diff --git a/tests/PHPStan/Rules/Comparison/BooleanOrConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/BooleanOrConstantConditionRuleTest.php index a1a399005e..1006feee88 100644 --- a/tests/PHPStan/Rules/Comparison/BooleanOrConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/BooleanOrConstantConditionRuleTest.php @@ -239,7 +239,6 @@ public function testReportPhpDoc(): void [ 'Right side of || is always true.', 33, - $tipText, ], ]); }