diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index 13e6788e40..516df23a7f 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -982,6 +982,7 @@ private function processStmtNode( foreach ($stmt->cond as $condExpr) { $condResult = $this->processExprNode($condExpr, $bodyScope, static function (): void { }, ExpressionContext::createDeep()); + $initScope = $condResult->getScope(); $condTruthiness = $condResult->getScope()->getType($condExpr)->toBoolean(); if ($condTruthiness instanceof ConstantBooleanType) { $condTruthinessTrinary = TrinaryLogic::createFromBoolean($condTruthiness->getValue()); diff --git a/tests/PHPStan/Analyser/NodeScopeResolverTest.php b/tests/PHPStan/Analyser/NodeScopeResolverTest.php index fe6bc8b534..aaae1e1b67 100644 --- a/tests/PHPStan/Analyser/NodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/NodeScopeResolverTest.php @@ -597,6 +597,11 @@ public function dataFileAsserts(): iterable yield from $this->gatherAssertTypes(__DIR__ . '/data/pdo-prepare.php'); yield from $this->gatherAssertTypes(__DIR__ . '/data/constant-array-type-set.php'); yield from $this->gatherAssertTypes(__DIR__ . '/data/for-loop-i-type.php'); + yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-5316.php'); + yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-3858.php'); + yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-2806.php'); + yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-5328.php'); + yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-3044.php'); } /** diff --git a/tests/PHPStan/Analyser/data/bug-2806.php b/tests/PHPStan/Analyser/data/bug-2806.php new file mode 100644 index 0000000000..a34e1233c1 --- /dev/null +++ b/tests/PHPStan/Analyser/data/bug-2806.php @@ -0,0 +1,15 @@ +> + */ + private function getIntArrayFloatArray(): array + { + return [ + 0 => [1.1, 2.2, 3.3], + 1 => [1.1, 2.2, 3.3], + 2 => [1.1, 2.2, 3.3], + ]; + } + + /** + * @return array> + */ + public function invalidType(): void + { + $X = $this->getIntArrayFloatArray(); + $L = $this->getIntArrayFloatArray(); + + $n = 3; + $m = 3; + + for ($k = 0; $k < $m; ++$k) { + for ($j = 0; $j < $n; ++$j) { + for ($i = 0; $i < $k; ++$i) { + $X[$k][$j] -= $X[$i][$j] * $L[$k][$i]; + } + } + } + + assertType('array>', $X); + } +} diff --git a/tests/PHPStan/Analyser/data/bug-3858.php b/tests/PHPStan/Analyser/data/bug-3858.php new file mode 100644 index 0000000000..341e64a9f6 --- /dev/null +++ b/tests/PHPStan/Analyser/data/bug-3858.php @@ -0,0 +1,25 @@ + 'foo', + 2 => 'foo', + 3 => 'bar', + ]; + $names = ['foo', 'bar', 'baz']; + $array = ['foo' => [], 'bar' => [], 'baz' => []]; + + foreach ($map as $value => $name) { + $array[$name][] = $value; + } + + + foreach ($array as $name => $elements) { + assertType('bool', count($elements) > 0); + assertType('array', $elements); + } +}; diff --git a/tests/PHPStan/Analyser/data/bug-5328.php b/tests/PHPStan/Analyser/data/bug-5328.php new file mode 100644 index 0000000000..5bb7c7d301 --- /dev/null +++ b/tests/PHPStan/Analyser/data/bug-5328.php @@ -0,0 +1,25 @@ +produceIntOrNull(); + for ($i = 0; $i < 5 && !is_int($int) ; $i++) { + $int = $this->produceIntOrNull(); + } + + assertType('int|null', $int); + } + +} diff --git a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php index 364850adc6..6cf86a184b 100644 --- a/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/ImpossibleCheckTypeFunctionCallRuleTest.php @@ -441,4 +441,11 @@ public function testArrayIsList(): void ]); } + public function testBug3766(): void + { + $this->checkAlwaysTrueCheckTypeFunctionCall = true; + $this->treatPhpDocTypesAsCertain = true; + $this->analyse([__DIR__ . '/data/bug-3766.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Comparison/NumberComparisonOperatorsConstantConditionRuleTest.php b/tests/PHPStan/Rules/Comparison/NumberComparisonOperatorsConstantConditionRuleTest.php index ac442f3017..47834ddd43 100644 --- a/tests/PHPStan/Rules/Comparison/NumberComparisonOperatorsConstantConditionRuleTest.php +++ b/tests/PHPStan/Rules/Comparison/NumberComparisonOperatorsConstantConditionRuleTest.php @@ -53,4 +53,14 @@ public function testBug5161(): void $this->analyse([__DIR__ . '/data/bug-5161.php'], []); } + public function testBug3310(): void + { + $this->analyse([__DIR__ . '/data/bug-3310.php'], []); + } + + public function testBug3264(): void + { + $this->analyse([__DIR__ . '/data/bug-3264.php'], []); + } + } diff --git a/tests/PHPStan/Rules/Comparison/data/bug-3264.php b/tests/PHPStan/Rules/Comparison/data/bug-3264.php new file mode 100644 index 0000000000..34fb93f0f2 --- /dev/null +++ b/tests/PHPStan/Rules/Comparison/data/bug-3264.php @@ -0,0 +1,17 @@ + + */ + function get_foo(): array + { + return []; + } + + public function doFoo(): void + { + $foo = $this->get_foo(); + for ($i = 0; $i < \count($foo); $i++) { + if (\array_key_exists($i + 1, $foo) + && \array_key_exists($i + 2, $foo) + ) { + echo $i; + } + } + } + +} diff --git a/tests/PHPStan/Rules/Properties/DefaultValueTypesAssignedToPropertiesRuleTest.php b/tests/PHPStan/Rules/Properties/DefaultValueTypesAssignedToPropertiesRuleTest.php index 05bdeb4c30..9f9e006fcb 100644 --- a/tests/PHPStan/Rules/Properties/DefaultValueTypesAssignedToPropertiesRuleTest.php +++ b/tests/PHPStan/Rules/Properties/DefaultValueTypesAssignedToPropertiesRuleTest.php @@ -48,4 +48,14 @@ public function testDefaultValueForNativePropertyType(): void ]); } + public function testBug5607(): void + { + $this->analyse([__DIR__ . '/data/bug-5607.php'], [ + [ + 'Property Bug5607\Cl::$u (Bug5607\A|null) does not accept default value of type array.', + 10, + ], + ]); + } + } diff --git a/tests/PHPStan/Rules/Properties/data/bug-5607.php b/tests/PHPStan/Rules/Properties/data/bug-5607.php new file mode 100644 index 0000000000..eff2724216 --- /dev/null +++ b/tests/PHPStan/Rules/Properties/data/bug-5607.php @@ -0,0 +1,19 @@ + 'basic segment']; + + /** + * @param array $x + */ + public function mm($x): void + { + throw new \Exception(); + } +}