diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 7acab4ce1f..d98c716fe1 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -1040,6 +1040,34 @@ private function resolveType(Expr $node): Type return new StringType(); } + if ( + $node instanceof Node\Expr\BinaryOp\Mul + || $node instanceof Node\Expr\AssignOp\Mul + ) { + if ($node instanceof Node\Expr\AssignOp) { + $leftType = $this->getType($node->var)->toNumber(); + $rightType = $this->getType($node->expr)->toNumber(); + } else { + $leftType = $this->getType($node->left)->toNumber(); + $rightType = $this->getType($node->right)->toNumber(); + } + + $floatType = new FloatType(); + + if ($leftType instanceof ConstantIntegerType && $leftType->getValue() === 0) { + if ($floatType->isSuperTypeOf($rightType)->yes()) { + return new ConstantFloatType(0.0); + } + return new ConstantIntegerType(0); + } + if ($rightType instanceof ConstantIntegerType && $rightType->getValue() === 0) { + if ($floatType->isSuperTypeOf($leftType)->yes()) { + return new ConstantFloatType(0.0); + } + return new ConstantIntegerType(0); + } + } + if ( $node instanceof Node\Expr\BinaryOp\Div || $node instanceof Node\Expr\AssignOp\Div diff --git a/tests/PHPStan/Analyser/data/math.php b/tests/PHPStan/Analyser/data/math.php index 6db10a4e70..42ac905c67 100644 --- a/tests/PHPStan/Analyser/data/math.php +++ b/tests/PHPStan/Analyser/data/math.php @@ -109,4 +109,34 @@ public function doSit(int $i, int $j): void assertType('int', $i - $j); } + /** + * @param int<-5, 5> $range + */ + public function multiplyZero(int $i, float $f, $range): void + { + assertType('0', $i * false); + assertType('0.0', $f * false); + assertType('0', $range * false); + + assertType('0', $i * '0'); + assertType('0.0', $f * '0'); + assertType('0', $range * '0'); + + assertType('0', $i * 0); + assertType('0.0', $f * 0); + assertType('0', $range * 0); + + assertType('0', 0 * $i); + assertType('0.0', 0 * $f); + assertType('0', 0 * $range); + + $i *= 0; + $f *= 0; + $range *= 0; + assertType('0', $i); + assertType('0.0', $f); + assertType('0', $range); + + } + }