Allow GMP and BCMath\Number in arithmetic operations#311
Allow GMP and BCMath\Number in arithmetic operations#311Firehed wants to merge 7 commits intophpstan:2.0.xfrom
Conversation
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
GMP has supported operator overloading since PHP 5.6. BCMath\Number has supported it since PHP 8.4. Fixes phpstan#310 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Strict-rules allows both as valid operand types. PHPStan core catches the type incompatibility. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
Why isn't this taking advantage of the existing extensions but instead hardcodes this information? |
|
Thanks for the feedback. To clarify - should the fix:
The core issue is that Just to clarify, I had something like this, but it felt weird: diff --git a/src/Rules/Operators/OperatorRuleHelper.php b/src/Rules/Operators/OperatorRuleHelper.php
--- a/src/Rules/Operators/OperatorRuleHelper.php
+++ b/src/Rules/Operators/OperatorRuleHelper.php
@@ -3,7 +3,9 @@
namespace PHPStan\Rules\Operators;
use PhpParser\Node\Expr;
+use PhpParser\Node\Scalar\Int_;
use PHPStan\Analyser\Scope;
+use PHPStan\Reflection\InitializerExprTypeResolver;
use PHPStan\Rules\RuleLevelHelper;
use PHPStan\Type\Accessory\AccessoryNumericStringType;
use PHPStan\Type\BenevolentUnionType;
@@ -21,9 +23,15 @@ class OperatorRuleHelper
private RuleLevelHelper $ruleLevelHelper;
- public function __construct(RuleLevelHelper $ruleLevelHelper)
+ private InitializerExprTypeResolver $initializerExprTypeResolver;
+
+ public function __construct(
+ RuleLevelHelper $ruleLevelHelper,
+ InitializerExprTypeResolver $initializerExprTypeResolver
+ )
{
$this->ruleLevelHelper = $ruleLevelHelper;
+ $this->initializerExprTypeResolver = $initializerExprTypeResolver;
}
public function isValidForArithmeticOperation(Scope $scope, Expr $expr): bool
@@ -33,13 +41,22 @@ class OperatorRuleHelper
return true;
}
- // already reported by PHPStan core
- if ($type->toNumber() instanceof ErrorType) {
+ if ($this->isSubtypeOfNumber($scope, $expr)) {
return true;
}
- return $this->isSubtypeOfNumber($scope, $expr);
+ // Check if the type supports arithmetic via operator overloading extensions
+ $intExpr = new Int_(1);
+ $resultType = $this->initializerExprTypeResolver->getPlusTypeFromTypes(
+ $expr,
+ $intExpr,
+ $type,
+ new IntegerType(),
+ );
+
+ if (!$resultType instanceof ErrorType) {
+ return true;
+ }
+
+ // Type doesn't support arithmetic - check if PHPStan core will report it
+ return $type->toNumber() instanceof ErrorType;
} |
|
What about |
Use $scope->getType() on a synthetic Plus operation to check if object types support arithmetic via operator overloading extensions. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
That seems to be quite a bit simpler, thanks for the tip! |
VincentLanglet
left a comment
There was a problem hiding this comment.
You also need some logic in isValidForIncrement and isValidForDecrement no ?
Summary
GMPandBcMath\Numberobjects in arithmetic operations (+,-,*,/,%,**, unary+/-)++/--) unchanged since those operators aren't supported by these typesFixes #310
Implementation
Modified
OperatorRuleHelper::isSubtypeOfNumber()to accept an optional parameter for including operator-overloaded types.isValidForArithmeticOperation()passestrueto include GMP and BCMath\Number.Question for reviewers
The test fixture includes
incompatibleOverloads()which testsGMP + BCMath\Number. These types are incompatible at runtime. The strict-rules correctly allow both as valid operand types (they are numeric-like), and PHPStan core is expected to catch the incompatibility viabinaryOp.invalid.However,
RuleTestCaseonly captures errors from the specific rule being tested, not PHPStan core errors. So this test only verifies strict-rules doesn't flag it - it doesn't verify PHPStan core catches the incompatibility.Is there a recommended way to add integration tests that verify PHPStan core behavior, or is this outside the scope of strict-rules' test suite?
Test plan
🤖 Generated with Claude Code