diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 6356f5512b..5da3325cf8 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -5409,15 +5409,24 @@ private function integerRangeMath(Type $range, Expr $node, Type $operand): Type if ($node instanceof Node\Expr\BinaryOp\Plus || $node instanceof Node\Expr\AssignOp\Plus) { if ($operand instanceof ConstantIntegerType) { + /** @var int|float|null $min */ $min = $rangeMin !== null ? $rangeMin + $operand->getValue() : null; + + /** @var int|float|null $max */ $max = $rangeMax !== null ? $rangeMax + $operand->getValue() : null; } else { + /** @var int|float|null $min */ $min = $rangeMin !== null && $operand->getMin() !== null ? $rangeMin + $operand->getMin() : null; + + /** @var int|float|null $max */ $max = $rangeMax !== null && $operand->getMax() !== null ? $rangeMax + $operand->getMax() : null; } } elseif ($node instanceof Node\Expr\BinaryOp\Minus || $node instanceof Node\Expr\AssignOp\Minus) { if ($operand instanceof ConstantIntegerType) { + /** @var int|float|null $min */ $min = $rangeMin !== null ? $rangeMin - $operand->getValue() : null; + + /** @var int|float|null $max */ $max = $rangeMax !== null ? $rangeMax - $operand->getValue() : null; } else { if ($rangeMin === $rangeMax && $rangeMin !== null @@ -5429,8 +5438,10 @@ private function integerRangeMath(Type $range, Expr $node, Type $operand): Type $min = null; } elseif ($rangeMin !== null) { if ($operand->getMax() !== null) { + /** @var int|float $min */ $min = $rangeMin - $operand->getMax(); } else { + /** @var int|float $min */ $min = $rangeMin - $operand->getMin(); } } else { @@ -5442,9 +5453,11 @@ private function integerRangeMath(Type $range, Expr $node, Type $operand): Type $max = null; } elseif ($rangeMax !== null) { if ($rangeMin !== null && $operand->getMin() === null) { + /** @var int|float $min */ $min = $rangeMin - $operand->getMax(); $max = null; } elseif ($operand->getMin() !== null) { + /** @var int|float $max */ $max = $rangeMax - $operand->getMin(); } else { $max = null; @@ -5460,10 +5473,16 @@ private function integerRangeMath(Type $range, Expr $node, Type $operand): Type } } elseif ($node instanceof Node\Expr\BinaryOp\Mul || $node instanceof Node\Expr\AssignOp\Mul) { if ($operand instanceof ConstantIntegerType) { + /** @var int|float|null $min */ $min = $rangeMin !== null ? $rangeMin * $operand->getValue() : null; + + /** @var int|float|null $max */ $max = $rangeMax !== null ? $rangeMax * $operand->getValue() : null; } else { + /** @var int|float|null $min */ $min = $rangeMin !== null && $operand->getMin() !== null ? $rangeMin * $operand->getMin() : null; + + /** @var int|float|null $max */ $max = $rangeMax !== null && $operand->getMax() !== null ? $rangeMax * $operand->getMax() : null; } @@ -5527,6 +5546,13 @@ private function integerRangeMath(Type $range, Expr $node, Type $operand): Type } } + if (is_float($min)) { + $min = null; + } + if (is_float($max)) { + $max = null; + } + return IntegerRangeType::fromInterval($min, $max); } diff --git a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php index ea2cc689e3..b54b16c461 100644 --- a/tests/PHPStan/Analyser/AnalyserIntegrationTest.php +++ b/tests/PHPStan/Analyser/AnalyserIntegrationTest.php @@ -500,6 +500,12 @@ public function testBug6300(): void $this->assertSame(24, $errors[1]->getLine()); } + public function testBug6466(): void + { + $errors = $this->runAnalyse(__DIR__ . '/data/bug-6466.php'); + $this->assertNoErrors($errors); + } + public function testBug6253(): void { $errors = $this->runAnalyse( diff --git a/tests/PHPStan/Analyser/data/bug-6466.php b/tests/PHPStan/Analyser/data/bug-6466.php new file mode 100644 index 0000000000..b529d7cbfc --- /dev/null +++ b/tests/PHPStan/Analyser/data/bug-6466.php @@ -0,0 +1,12 @@ +