From c5ee1fec37a655859b3fcdc42a1ef0011a3cc40a Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 28 Jul 2026 16:12:57 +0700 Subject: [PATCH 1/2] [DeadCode] Skip negative zero on RemoveDeadZeroAndOneOperationRector --- .../Fixture/skip_negative_zero.php.inc | 15 +++++++++++ .../RemoveDeadZeroAndOneOperationRector.php | 25 ++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 rules-tests/DeadCode/Rector/Plus/RemoveDeadZeroAndOneOperationRector/Fixture/skip_negative_zero.php.inc diff --git a/rules-tests/DeadCode/Rector/Plus/RemoveDeadZeroAndOneOperationRector/Fixture/skip_negative_zero.php.inc b/rules-tests/DeadCode/Rector/Plus/RemoveDeadZeroAndOneOperationRector/Fixture/skip_negative_zero.php.inc new file mode 100644 index 00000000000..9f7af43a966 --- /dev/null +++ b/rules-tests/DeadCode/Rector/Plus/RemoveDeadZeroAndOneOperationRector/Fixture/skip_negative_zero.php.inc @@ -0,0 +1,15 @@ +isIntegerType($assignOp->var)) { + return null; + } + if ($this->nodeTypeResolver->isNumberType($assignOp->var)) { return $assignOp->var; } @@ -152,7 +157,13 @@ private function processBinaryPlusAndMinus(Plus|Minus $binaryOp): ?Expr return null; } - if ($this->isLiteralZero($binaryOp->left) && $this->nodeTypeResolver->isNumberType($binaryOp->right)) { + if ($this->isLiteralZero($binaryOp->left)) { + // on float, 0 + $x normalizes negative zero (-0.0) to 0.0 and 0 - $x flips its sign, + // so the operation is not dead + if (! $this->isIntegerType($binaryOp->right)) { + return null; + } + if ($binaryOp instanceof Minus) { return new UnaryMinus($binaryOp->right); } @@ -164,6 +175,11 @@ private function processBinaryPlusAndMinus(Plus|Minus $binaryOp): ?Expr return null; } + // on float, $x + 0 normalizes negative zero (-0.0) to 0.0, so it is not dead + if ($binaryOp instanceof Plus && ! $this->isIntegerType($binaryOp->left)) { + return null; + } + return $binaryOp->left; } @@ -237,4 +253,11 @@ private function isLiteralZero(Expr $expr): bool { return $expr instanceof Int_ && $expr->value === 0; } + + private function isIntegerType(Expr $expr): bool + { + return $this->nodeTypeResolver->getNativeType($expr) + ->isInteger() + ->yes(); + } } From cbeb7c162f0c49f99bb35ddd364796e546483d85 Mon Sep 17 00:00:00 2001 From: Abdul Malik Ikhsan Date: Tue, 28 Jul 2026 16:16:20 +0700 Subject: [PATCH 2/2] assignplus --- .../skip_assign_plus_negative_zero.php.inc | 15 +++++++++++++++ .../skip_zero_minus_positive_zero.php.inc | 15 +++++++++++++++ .../skip_zero_plus_negative_zero.php.inc | 15 +++++++++++++++ .../RemoveDeadZeroAndOneOperationRector.php | 19 +++++++++---------- 4 files changed, 54 insertions(+), 10 deletions(-) create mode 100644 rules-tests/DeadCode/Rector/Plus/RemoveDeadZeroAndOneOperationRector/Fixture/skip_assign_plus_negative_zero.php.inc create mode 100644 rules-tests/DeadCode/Rector/Plus/RemoveDeadZeroAndOneOperationRector/Fixture/skip_zero_minus_positive_zero.php.inc create mode 100644 rules-tests/DeadCode/Rector/Plus/RemoveDeadZeroAndOneOperationRector/Fixture/skip_zero_plus_negative_zero.php.inc diff --git a/rules-tests/DeadCode/Rector/Plus/RemoveDeadZeroAndOneOperationRector/Fixture/skip_assign_plus_negative_zero.php.inc b/rules-tests/DeadCode/Rector/Plus/RemoveDeadZeroAndOneOperationRector/Fixture/skip_assign_plus_negative_zero.php.inc new file mode 100644 index 00000000000..8a34b5029ab --- /dev/null +++ b/rules-tests/DeadCode/Rector/Plus/RemoveDeadZeroAndOneOperationRector/Fixture/skip_assign_plus_negative_zero.php.inc @@ -0,0 +1,15 @@ +isIntegerType($assignOp->var)) { + if ($assignOp instanceof AssignPlus && ! $this->nodeTypeResolver->getNativeType($assignOp->var) + ->isInteger() + ->yes()) { return null; } @@ -160,7 +162,9 @@ private function processBinaryPlusAndMinus(Plus|Minus $binaryOp): ?Expr if ($this->isLiteralZero($binaryOp->left)) { // on float, 0 + $x normalizes negative zero (-0.0) to 0.0 and 0 - $x flips its sign, // so the operation is not dead - if (! $this->isIntegerType($binaryOp->right)) { + if (! $this->nodeTypeResolver->getNativeType($binaryOp->right) + ->isInteger() + ->yes()) { return null; } @@ -176,7 +180,9 @@ private function processBinaryPlusAndMinus(Plus|Minus $binaryOp): ?Expr } // on float, $x + 0 normalizes negative zero (-0.0) to 0.0, so it is not dead - if ($binaryOp instanceof Plus && ! $this->isIntegerType($binaryOp->left)) { + if ($binaryOp instanceof Plus && ! $this->nodeTypeResolver->getNativeType($binaryOp->left) + ->isInteger() + ->yes()) { return null; } @@ -253,11 +259,4 @@ private function isLiteralZero(Expr $expr): bool { return $expr instanceof Int_ && $expr->value === 0; } - - private function isIntegerType(Expr $expr): bool - { - return $this->nodeTypeResolver->getNativeType($expr) - ->isInteger() - ->yes(); - } }