From e7063f33c053396d721497e38506ad1a6e7ac067 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sun, 2 Mar 2025 10:44:02 +0100 Subject: [PATCH 1/3] BCMath operator overloading extension --- conf/config.neon | 4 + src/Php/PhpVersion.php | 5 + .../InitializerExprTypeResolver.php | 15 +- src/Type/ObjectType.php | 15 +- ...hNumberOperatorTypeSpecifyingExtension.php | 53 ++ .../Analyser/NodeScopeResolverTest.php | 4 + .../InvalidBinaryOperationRuleTest.php | 522 ++++++++++++++++++ .../Rules/Operators/data/bcmath-number.php | 406 ++++++++++++++ 8 files changed, 1018 insertions(+), 6 deletions(-) create mode 100644 src/Type/Php/BcMathNumberOperatorTypeSpecifyingExtension.php create mode 100644 tests/PHPStan/Rules/Operators/data/bcmath-number.php diff --git a/conf/config.neon b/conf/config.neon index b7e91bd3d9..54f4ff3186 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -1053,6 +1053,10 @@ services: arguments: reportMagicProperties: %reportMagicProperties% checkDynamicProperties: %checkDynamicProperties% + - + class: PHPStan\Type\Php\BcMathNumberOperatorTypeSpecifyingExtension + tags: + - phpstan.broker.operatorTypeSpecifyingExtension - class: PHPStan\Rules\Properties\UninitializedPropertyRule diff --git a/src/Php/PhpVersion.php b/src/Php/PhpVersion.php index 6f55bdda15..5215a30606 100644 --- a/src/Php/PhpVersion.php +++ b/src/Php/PhpVersion.php @@ -400,4 +400,9 @@ public function substrReturnFalseInsteadOfEmptyString(): bool return $this->versionId < 80000; } + public function supportsBcMathNumberOperatorOverloading(): bool + { + return $this->versionId >= 80400; + } + } diff --git a/src/Reflection/InitializerExprTypeResolver.php b/src/Reflection/InitializerExprTypeResolver.php index 9fef24a587..fb935ac630 100644 --- a/src/Reflection/InitializerExprTypeResolver.php +++ b/src/Reflection/InitializerExprTypeResolver.php @@ -872,6 +872,11 @@ public function getModType(Expr $left, Expr $right, callable $getTypeCallback): return $this->getNeverType($leftType, $rightType); } + $extensionSpecified = $this->callOperatorTypeSpecifyingExtensions(new BinaryOp\Mod($left, $right), $leftType, $rightType); + if ($extensionSpecified !== null) { + return $extensionSpecified; + } + if ($leftType->toNumber() instanceof ErrorType || $rightType->toNumber() instanceof ErrorType) { return new ErrorType(); } @@ -1234,16 +1239,16 @@ public function getPowType(Expr $left, Expr $right, callable $getTypeCallback): $leftType = $getTypeCallback($left); $rightType = $getTypeCallback($right); - $exponentiatedTyped = $leftType->exponentiate($rightType); - if (!$exponentiatedTyped instanceof ErrorType) { - return $exponentiatedTyped; - } - $extensionSpecified = $this->callOperatorTypeSpecifyingExtensions(new BinaryOp\Pow($left, $right), $leftType, $rightType); if ($extensionSpecified !== null) { return $extensionSpecified; } + $exponentiatedTyped = $leftType->exponentiate($rightType); + if (!$exponentiatedTyped instanceof ErrorType) { + return $exponentiatedTyped; + } + return new ErrorType(); } diff --git a/src/Type/ObjectType.php b/src/Type/ObjectType.php index 0ad78520f2..5a05575059 100644 --- a/src/Type/ObjectType.php +++ b/src/Type/ObjectType.php @@ -31,6 +31,8 @@ use PHPStan\Reflection\Type\UnresolvedPropertyPrototypeReflection; use PHPStan\ShouldNotHappenException; use PHPStan\TrinaryLogic; +use PHPStan\Type\Accessory\AccessoryNonEmptyStringType; +use PHPStan\Type\Accessory\AccessoryNumericStringType; use PHPStan\Type\Constant\ConstantArrayType; use PHPStan\Type\Constant\ConstantBooleanType; use PHPStan\Type\Constant\ConstantStringType; @@ -593,6 +595,14 @@ public function toFloat(): Type public function toString(): Type { + if ($this->isInstanceOf('BcMath\Number')->yes()) { + return new IntersectionType([ + new StringType(), + new AccessoryNumericStringType(), + new AccessoryNonEmptyStringType(), + ]); + } + $classReflection = $this->getClassReflection(); if ($classReflection === null) { return new ErrorType(); @@ -678,7 +688,10 @@ public function toCoercedArgumentType(bool $strictTypes): Type public function toBoolean(): BooleanType { - if ($this->isInstanceOf('SimpleXMLElement')->yes()) { + if ( + $this->isInstanceOf('SimpleXMLElement')->yes() + || $this->isInstanceOf('BcMath\Number')->yes() + ) { return new BooleanType(); } diff --git a/src/Type/Php/BcMathNumberOperatorTypeSpecifyingExtension.php b/src/Type/Php/BcMathNumberOperatorTypeSpecifyingExtension.php new file mode 100644 index 0000000000..3e0d793052 --- /dev/null +++ b/src/Type/Php/BcMathNumberOperatorTypeSpecifyingExtension.php @@ -0,0 +1,53 @@ +phpVersion->supportsBcMathNumberOperatorOverloading() || $leftSide instanceof NeverType || $rightSide instanceof NeverType) { + return false; + } + + $bcMathNumberType = new ObjectType('BcMath\Number'); + + return in_array($operatorSigil, ['-', '+', '*', '/', '**', '%'], true) + && ( + $bcMathNumberType->isSuperTypeOf($leftSide)->yes() + || $bcMathNumberType->isSuperTypeOf($rightSide)->yes() + ); + } + + public function specifyType(string $operatorSigil, Type $leftSide, Type $rightSide): Type + { + $bcMathNumberType = new ObjectType('BcMath\Number'); + $otherSide = $bcMathNumberType->isSuperTypeOf($leftSide)->yes() + ? $rightSide + : $leftSide; + + if ( + $otherSide->isInteger()->yes() + || $otherSide->isNumericString()->yes() + || $bcMathNumberType->isSuperTypeOf($otherSide)->yes() + ) { + return $bcMathNumberType; + } + + return new ErrorType(); + } + +} diff --git a/tests/PHPStan/Analyser/NodeScopeResolverTest.php b/tests/PHPStan/Analyser/NodeScopeResolverTest.php index 7f3d9638b2..5a0ad0f06d 100644 --- a/tests/PHPStan/Analyser/NodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/NodeScopeResolverTest.php @@ -196,6 +196,10 @@ private static function findTestFiles(): iterable yield __DIR__ . '/../Rules/Comparison/data/bug-9499.php'; } + if (PHP_VERSION_ID >= 80400) { + yield __DIR__ . '/../Rules/Operators/data/bcmath-number.php'; + } + yield __DIR__ . '/../Rules/PhpDoc/data/bug-8609-function.php'; yield __DIR__ . '/../Rules/Comparison/data/bug-5365.php'; yield __DIR__ . '/../Rules/Comparison/data/bug-6551.php'; diff --git a/tests/PHPStan/Rules/Operators/InvalidBinaryOperationRuleTest.php b/tests/PHPStan/Rules/Operators/InvalidBinaryOperationRuleTest.php index 135194070b..64b27ccb21 100644 --- a/tests/PHPStan/Rules/Operators/InvalidBinaryOperationRuleTest.php +++ b/tests/PHPStan/Rules/Operators/InvalidBinaryOperationRuleTest.php @@ -303,6 +303,528 @@ public function testBug5309(): void $this->analyse([__DIR__ . '/data/bug-5309.php'], []); } + public function testBcMathNumber(): void + { + if (PHP_VERSION_ID < 80400) { + self::markTestSkipped('Test requires PHP 8.4.'); + } + + $this->analyse([__DIR__ . '/data/bcmath-number.php'], [ + [ + 'Binary operation "<<" between BcMath\\Number and BcMath\\Number results in an error.', + 19, + ], + [ + 'Binary operation ">>" between BcMath\\Number and BcMath\\Number results in an error.', + 20, + ], + [ + 'Binary operation "&" between BcMath\\Number and BcMath\\Number results in an error.', + 28, + ], + [ + 'Binary operation "^" between BcMath\\Number and BcMath\\Number results in an error.', + 29, + ], + [ + 'Binary operation "|" between BcMath\\Number and BcMath\\Number results in an error.', + 30, + ], + [ + 'Binary operation "<<" between BcMath\\Number and int results in an error.', + 47, + ], + [ + 'Binary operation ">>" between BcMath\\Number and int results in an error.', + 48, + ], + [ + 'Binary operation "&" between BcMath\\Number and int results in an error.', + 56, + ], + [ + 'Binary operation "^" between BcMath\\Number and int results in an error.', + 57, + ], + [ + 'Binary operation "|" between BcMath\\Number and int results in an error.', + 58, + ], + [ + 'Binary operation "+" between BcMath\\Number and float results in an error.', + 68, + ], + [ + 'Binary operation "-" between BcMath\\Number and float results in an error.', + 69, + ], + [ + 'Binary operation "*" between BcMath\\Number and float results in an error.', + 70, + ], + [ + 'Binary operation "/" between BcMath\\Number and float results in an error.', + 71, + ], + [ + 'Binary operation "%" between BcMath\\Number and float results in an error.', + 72, + ], + [ + 'Binary operation "**" between BcMath\\Number and float results in an error.', + 74, + ], + [ + 'Binary operation "<<" between BcMath\\Number and float results in an error.', + 75, + ], + [ + 'Binary operation ">>" between BcMath\\Number and float results in an error.', + 76, + ], + [ + 'Binary operation "&" between BcMath\\Number and float results in an error.', + 84, + ], + [ + 'Binary operation "^" between BcMath\\Number and float results in an error.', + 85, + ], + [ + 'Binary operation "|" between BcMath\\Number and float results in an error.', + 86, + ], + [ + 'Binary operation "<<" between BcMath\\Number and numeric-string results in an error.', + 104, + ], + [ + 'Binary operation ">>" between BcMath\\Number and numeric-string results in an error.', + 105, + ], + [ + 'Binary operation "&" between BcMath\\Number and numeric-string results in an error.', + 113, + ], + [ + 'Binary operation "^" between BcMath\\Number and numeric-string results in an error.', + 114, + ], + [ + 'Binary operation "|" between BcMath\\Number and numeric-string results in an error.', + 115, + ], + [ + 'Binary operation "+" between BcMath\\Number and string results in an error.', + 125, + ], + [ + 'Binary operation "-" between BcMath\\Number and string results in an error.', + 126, + ], + [ + 'Binary operation "*" between BcMath\\Number and string results in an error.', + 127, + ], + [ + 'Binary operation "/" between BcMath\\Number and string results in an error.', + 128, + ], + [ + 'Binary operation "%" between BcMath\\Number and string results in an error.', + 129, + ], + [ + 'Binary operation "**" between BcMath\\Number and string results in an error.', + 131, + ], + [ + 'Binary operation "<<" between BcMath\\Number and string results in an error.', + 132, + ], + [ + 'Binary operation ">>" between BcMath\\Number and string results in an error.', + 133, + ], + [ + 'Binary operation "&" between BcMath\\Number and string results in an error.', + 141, + ], + [ + 'Binary operation "^" between BcMath\\Number and string results in an error.', + 142, + ], + [ + 'Binary operation "|" between BcMath\\Number and string results in an error.', + 143, + ], + [ + 'Binary operation "+" between BcMath\\Number and bool results in an error.', + 153, + ], + [ + 'Binary operation "-" between BcMath\\Number and bool results in an error.', + 154, + ], + [ + 'Binary operation "*" between BcMath\\Number and bool results in an error.', + 155, + ], + [ + 'Binary operation "/" between BcMath\\Number and bool results in an error.', + 156, + ], + [ + 'Binary operation "%" between BcMath\\Number and bool results in an error.', + 157, + ], + [ + 'Binary operation "**" between BcMath\\Number and bool results in an error.', + 159, + ], + [ + 'Binary operation "<<" between BcMath\\Number and bool results in an error.', + 160, + ], + [ + 'Binary operation ">>" between BcMath\\Number and bool results in an error.', + 161, + ], + [ + 'Binary operation "&" between BcMath\\Number and bool results in an error.', + 169, + ], + [ + 'Binary operation "^" between BcMath\\Number and bool results in an error.', + 170, + ], + [ + 'Binary operation "|" between BcMath\\Number and bool results in an error.', + 171, + ], + [ + 'Binary operation "+" between BcMath\\Number and null results in an error.', + 182, + ], + [ + 'Binary operation "-" between BcMath\\Number and null results in an error.', + 183, + ], + [ + 'Binary operation "/" between BcMath\\Number and null results in an error.', + 185, + ], + [ + 'Binary operation "%" between BcMath\\Number and null results in an error.', + 186, + ], + [ + 'Binary operation "**" between BcMath\\Number and null results in an error.', + 188, + ], + [ + 'Binary operation "<<" between BcMath\\Number and null results in an error.', + 189, + ], + [ + 'Binary operation ">>" between BcMath\\Number and null results in an error.', + 190, + ], + [ + 'Binary operation "&" between BcMath\\Number and null results in an error.', + 198, + ], + [ + 'Binary operation "^" between BcMath\\Number and null results in an error.', + 199, + ], + [ + 'Binary operation "|" between BcMath\\Number and null results in an error.', + 200, + ], + [ + 'Binary operation "+" between BcMath\\Number and array results in an error.', + 210, + ], + [ + 'Binary operation "-" between BcMath\\Number and array results in an error.', + 211, + ], + [ + 'Binary operation "*" between BcMath\\Number and array results in an error.', + 212, + ], + [ + 'Binary operation "/" between BcMath\\Number and array results in an error.', + 213, + ], + [ + 'Binary operation "%" between BcMath\\Number and array results in an error.', + 214, + ], + [ + 'Binary operation "." between BcMath\\Number and array results in an error.', + 215, + ], + [ + 'Binary operation "**" between BcMath\\Number and array results in an error.', + 216, + ], + [ + 'Binary operation "<<" between BcMath\\Number and array results in an error.', + 217, + ], + [ + 'Binary operation ">>" between BcMath\\Number and array results in an error.', + 218, + ], + [ + 'Binary operation "&" between BcMath\\Number and array results in an error.', + 226, + ], + [ + 'Binary operation "^" between BcMath\\Number and array results in an error.', + 227, + ], + [ + 'Binary operation "|" between BcMath\\Number and array results in an error.', + 228, + ], + [ + 'Binary operation "+" between BcMath\\Number and object results in an error.', + 238, + ], + [ + 'Binary operation "-" between BcMath\\Number and object results in an error.', + 239, + ], + [ + 'Binary operation "*" between BcMath\\Number and object results in an error.', + 240, + ], + [ + 'Binary operation "/" between BcMath\\Number and object results in an error.', + 241, + ], + [ + 'Binary operation "%" between BcMath\\Number and object results in an error.', + 242, + ], + [ + 'Binary operation "." between BcMath\\Number and object results in an error.', + 243, + ], + [ + 'Binary operation "**" between BcMath\\Number and object results in an error.', + 244, + ], + [ + 'Binary operation "<<" between BcMath\\Number and object results in an error.', + 245, + ], + [ + 'Binary operation ">>" between BcMath\\Number and object results in an error.', + 246, + ], + [ + 'Binary operation "&" between BcMath\\Number and object results in an error.', + 254, + ], + [ + 'Binary operation "^" between BcMath\\Number and object results in an error.', + 255, + ], + [ + 'Binary operation "|" between BcMath\\Number and object results in an error.', + 256, + ], + [ + 'Binary operation "+" between BcMath\\Number and resource results in an error.', + 267, + ], + [ + 'Binary operation "-" between BcMath\\Number and resource results in an error.', + 268, + ], + [ + 'Binary operation "*" between BcMath\\Number and resource results in an error.', + 269, + ], + [ + 'Binary operation "/" between BcMath\\Number and resource results in an error.', + 270, + ], + [ + 'Binary operation "%" between BcMath\\Number and resource results in an error.', + 271, + ], + [ + 'Binary operation "**" between BcMath\\Number and resource results in an error.', + 273, + ], + [ + 'Binary operation "<<" between BcMath\\Number and resource results in an error.', + 274, + ], + [ + 'Binary operation ">>" between BcMath\\Number and resource results in an error.', + 275, + ], + [ + 'Binary operation "&" between BcMath\\Number and resource results in an error.', + 283, + ], + [ + 'Binary operation "^" between BcMath\\Number and resource results in an error.', + 284, + ], + [ + 'Binary operation "|" between BcMath\\Number and resource results in an error.', + 285, + ], + [ + 'Binary operation "+" between BcMath\\Number and callable(): mixed results in an error.', + 295, + ], + [ + 'Binary operation "-" between BcMath\\Number and callable(): mixed results in an error.', + 296, + ], + [ + 'Binary operation "*" between BcMath\\Number and callable(): mixed results in an error.', + 297, + ], + [ + 'Binary operation "/" between BcMath\\Number and callable(): mixed results in an error.', + 298, + ], + [ + 'Binary operation "%" between BcMath\\Number and callable(): mixed results in an error.', + 299, + ], + [ + 'Binary operation "." between BcMath\\Number and callable(): mixed results in an error.', + 300, + ], + [ + 'Binary operation "**" between BcMath\\Number and callable(): mixed results in an error.', + 301, + ], + [ + 'Binary operation "<<" between BcMath\\Number and callable(): mixed results in an error.', + 302, + ], + [ + 'Binary operation ">>" between BcMath\\Number and callable(): mixed results in an error.', + 303, + ], + [ + 'Binary operation "&" between BcMath\\Number and callable(): mixed results in an error.', + 311, + ], + [ + 'Binary operation "^" between BcMath\\Number and callable(): mixed results in an error.', + 312, + ], + [ + 'Binary operation "|" between BcMath\\Number and callable(): mixed results in an error.', + 313, + ], + [ + 'Binary operation "+" between BcMath\\Number and iterable results in an error.', + 323, + ], + [ + 'Binary operation "-" between BcMath\\Number and iterable results in an error.', + 324, + ], + [ + 'Binary operation "*" between BcMath\\Number and iterable results in an error.', + 325, + ], + [ + 'Binary operation "/" between BcMath\\Number and iterable results in an error.', + 326, + ], + [ + 'Binary operation "%" between BcMath\\Number and iterable results in an error.', + 327, + ], + [ + 'Binary operation "." between BcMath\\Number and iterable results in an error.', + 328, + ], + [ + 'Binary operation "**" between BcMath\\Number and iterable results in an error.', + 329, + ], + [ + 'Binary operation "<<" between BcMath\\Number and iterable results in an error.', + 330, + ], + [ + 'Binary operation ">>" between BcMath\\Number and iterable results in an error.', + 331, + ], + [ + 'Binary operation "&" between BcMath\\Number and iterable results in an error.', + 339, + ], + [ + 'Binary operation "^" between BcMath\\Number and iterable results in an error.', + 340, + ], + [ + 'Binary operation "|" between BcMath\\Number and iterable results in an error.', + 341, + ], + [ + 'Binary operation "+" between BcMath\\Number and Stringable results in an error.', + 351, + ], + [ + 'Binary operation "-" between BcMath\\Number and Stringable results in an error.', + 352, + ], + [ + 'Binary operation "*" between BcMath\\Number and Stringable results in an error.', + 353, + ], + [ + 'Binary operation "/" between BcMath\\Number and Stringable results in an error.', + 354, + ], + [ + 'Binary operation "%" between BcMath\\Number and Stringable results in an error.', + 355, + ], + [ + 'Binary operation "**" between BcMath\\Number and Stringable results in an error.', + 357, + ], + [ + 'Binary operation "<<" between BcMath\\Number and Stringable results in an error.', + 358, + ], + [ + 'Binary operation ">>" between BcMath\\Number and Stringable results in an error.', + 359, + ], + [ + 'Binary operation "&" between BcMath\\Number and Stringable results in an error.', + 367, + ], + [ + 'Binary operation "^" between BcMath\\Number and Stringable results in an error.', + 368, + ], + [ + 'Binary operation "|" between BcMath\\Number and Stringable results in an error.', + 369, + ], + ]); + } + public function testBinaryMixed(): void { if (PHP_VERSION_ID < 80000) { diff --git a/tests/PHPStan/Rules/Operators/data/bcmath-number.php b/tests/PHPStan/Rules/Operators/data/bcmath-number.php new file mode 100644 index 0000000000..361ca4b275 --- /dev/null +++ b/tests/PHPStan/Rules/Operators/data/bcmath-number.php @@ -0,0 +1,406 @@ += 8.4 + +namespace BcMathNumber; + +use BcMath\Number; +use function PHPStan\Testing\assertType; + +class Foo +{ + public function bcVsBc(Number $a, Number $b): void + { + assertType('BcMath\Number', $a + $b); + assertType('BcMath\Number', $a - $b); + assertType('BcMath\Number', $a * $b); + assertType('BcMath\Number', $a / $b); + assertType('BcMath\Number', $a % $b); + assertType('non-falsy-string', $a . $b); + assertType('BcMath\Number', $a ** $b); + assertType('*ERROR*', $a << $b); + assertType('*ERROR*', $a >> $b); + assertType('bool', $a < $b); + assertType('bool', $a <= $b); + assertType('bool', $a > $b); + assertType('bool', $a >= $b); + assertType('int<-1, 1>', $a <=> $b); + assertType('bool', $a == $b); + assertType('bool', $a != $b); + assertType('*ERROR*', $a & $b); + assertType('*ERROR*', $a ^ $b); + assertType('*ERROR*', $a | $b); + assertType('bool', $a && $b); + assertType('bool', $a || $b); + assertType('bool', $a and $b); + assertType('bool', $a xor $b); + assertType('bool', $a or $b); + } + + public function bcVsInt(Number $a, int $b): void + { + assertType('BcMath\Number', $a + $b); + assertType('BcMath\Number', $a - $b); + assertType('BcMath\Number', $a * $b); + assertType('BcMath\Number', $a / $b); + assertType('BcMath\Number', $a % $b); + assertType('non-falsy-string', $a . $b); + assertType('BcMath\Number', $a ** $b); + assertType('*ERROR*', $a << $b); + assertType('*ERROR*', $a >> $b); + assertType('bool', $a < $b); + assertType('bool', $a <= $b); + assertType('bool', $a > $b); + assertType('bool', $a >= $b); + assertType('int<-1, 1>', $a <=> $b); + assertType('bool', $a == $b); + assertType('bool', $a != $b); + assertType('*ERROR*', $a & $b); + assertType('*ERROR*', $a ^ $b); + assertType('*ERROR*', $a | $b); + assertType('bool', $a && $b); + assertType('bool', $a || $b); + assertType('bool', $a and $b); + assertType('bool', $a xor $b); + assertType('bool', $a or $b); + } + + public function bcVsFloat(Number $a, float $b): void + { + assertType('*ERROR*', $a + $b); + assertType('*ERROR*', $a - $b); + assertType('*ERROR*', $a * $b); + assertType('*ERROR*', $a / $b); + assertType('*ERROR*', $a % $b); + assertType('non-falsy-string', $a . $b); + assertType('*ERROR*', $a ** $b); + assertType('*ERROR*', $a << $b); + assertType('*ERROR*', $a >> $b); + assertType('bool', $a < $b); + assertType('bool', $a <= $b); + assertType('bool', $a > $b); + assertType('bool', $a >= $b); + assertType('int<-1, 1>', $a <=> $b); + assertType('bool', $a == $b); + assertType('bool', $a != $b); + assertType('*ERROR*', $a & $b); + assertType('*ERROR*', $a ^ $b); + assertType('*ERROR*', $a | $b); + assertType('bool', $a && $b); + assertType('bool', $a || $b); + assertType('bool', $a and $b); + assertType('bool', $a xor $b); + assertType('bool', $a or $b); + } + + /** @param numeric-string $b */ + public function bcVsNumericString(Number $a, string $b): void + { + assertType('BcMath\Number', $a + $b); + assertType('BcMath\Number', $a - $b); + assertType('BcMath\Number', $a * $b); + assertType('BcMath\Number', $a / $b); + assertType('BcMath\Number', $a % $b); + assertType('non-falsy-string', $a . $b); + assertType('BcMath\Number', $a ** $b); + assertType('*ERROR*', $a << $b); + assertType('*ERROR*', $a >> $b); + assertType('bool', $a < $b); + assertType('bool', $a <= $b); + assertType('bool', $a > $b); + assertType('bool', $a >= $b); + assertType('int<-1, 1>', $a <=> $b); + assertType('bool', $a == $b); + assertType('bool', $a != $b); + assertType('*ERROR*', $a & $b); + assertType('*ERROR*', $a ^ $b); + assertType('*ERROR*', $a | $b); + assertType('bool', $a && $b); + assertType('bool', $a || $b); + assertType('bool', $a and $b); + assertType('bool', $a xor $b); + assertType('bool', $a or $b); + } + + public function bcVsNonNumericString(Number $a, string $b): void + { + assertType('*ERROR*', $a + $b); + assertType('*ERROR*', $a - $b); + assertType('*ERROR*', $a * $b); + assertType('*ERROR*', $a / $b); + assertType('*ERROR*', $a % $b); + assertType('non-empty-string', $a . $b); + assertType('*ERROR*', $a ** $b); + assertType('*ERROR*', $a << $b); + assertType('*ERROR*', $a >> $b); + assertType('bool', $a < $b); + assertType('bool', $a <= $b); + assertType('bool', $a > $b); + assertType('bool', $a >= $b); + assertType('int<-1, 1>', $a <=> $b); + assertType('bool', $a == $b); + assertType('bool', $a != $b); + assertType('*ERROR*', $a & $b); + assertType('*ERROR*', $a ^ $b); + assertType('*ERROR*', $a | $b); + assertType('bool', $a && $b); + assertType('bool', $a || $b); + assertType('bool', $a and $b); + assertType('bool', $a xor $b); + assertType('bool', $a or $b); + } + + public function bcVsBool(Number $a, bool $b): void + { + assertType('*ERROR*', $a + $b); + assertType('*ERROR*', $a - $b); + assertType('*ERROR*', $a * $b); + assertType('*ERROR*', $a / $b); + assertType('*ERROR*', $a % $b); + assertType('non-empty-string&numeric-string', $a . $b); + assertType('*ERROR*', $a ** $b); + assertType('*ERROR*', $a << $b); + assertType('*ERROR*', $a >> $b); + assertType('bool', $a < $b); + assertType('bool', $a <= $b); + assertType('bool', $a > $b); + assertType('bool', $a >= $b); + assertType('int<-1, 1>', $a <=> $b); + assertType('bool', $a == $b); + assertType('bool', $a != $b); + assertType('*ERROR*', $a & $b); + assertType('*ERROR*', $a ^ $b); + assertType('*ERROR*', $a | $b); + assertType('bool', $a && $b); + assertType('bool', $a || $b); + assertType('bool', $a and $b); + assertType('bool', $a xor $b); + assertType('bool', $a or $b); + } + + public function bcVsNull(Number $a): void + { + $b = null; + assertType('*ERROR*', $a + $b); + assertType('*ERROR*', $a - $b); + assertType('0', $a * $b); // BUG: This throws type error, but getMulType assumes that since null (mostly) behaves like zero, it will be zero. + assertType('*ERROR*', $a / $b); + assertType('*ERROR*', $a % $b); + assertType('non-empty-string&numeric-string', $a . $b); + assertType('*ERROR*', $a ** $b); + assertType('*ERROR*', $a << $b); + assertType('*ERROR*', $a >> $b); + assertType('bool', $a < $b); + assertType('bool', $a <= $b); + assertType('bool', $a > $b); + assertType('bool', $a >= $b); + assertType('int<-1, 1>', $a <=> $b); + assertType('bool', $a == $b); + assertType('bool', $a != $b); + assertType('*ERROR*', $a & $b); + assertType('*ERROR*', $a ^ $b); + assertType('*ERROR*', $a | $b); + assertType('false', $a && $b); + assertType('bool', $a || $b); + assertType('false', $a and $b); + assertType('bool', $a xor $b); + assertType('bool', $a or $b); + } + + public function bcVsArray(Number $a, array $b): void + { + assertType('*ERROR*', $a + $b); + assertType('*ERROR*', $a - $b); + assertType('*ERROR*', $a * $b); + assertType('*ERROR*', $a / $b); + assertType('*ERROR*', $a % $b); + assertType('*ERROR*', $a . $b); + assertType('*ERROR*', $a ** $b); + assertType('*ERROR*', $a << $b); + assertType('*ERROR*', $a >> $b); + assertType('bool', $a < $b); + assertType('bool', $a <= $b); + assertType('bool', $a > $b); + assertType('bool', $a >= $b); + assertType('int<-1, 1>', $a <=> $b); + assertType('bool', $a == $b); + assertType('bool', $a != $b); + assertType('*ERROR*', $a & $b); + assertType('*ERROR*', $a ^ $b); + assertType('*ERROR*', $a | $b); + assertType('bool', $a && $b); + assertType('bool', $a || $b); + assertType('bool', $a and $b); + assertType('bool', $a xor $b); + assertType('bool', $a or $b); + } + + public function bcVsObject(Number $a, object $b): void + { + assertType('*ERROR*', $a + $b); + assertType('*ERROR*', $a - $b); + assertType('*ERROR*', $a * $b); + assertType('*ERROR*', $a / $b); + assertType('*ERROR*', $a % $b); + assertType('*ERROR*', $a . $b); + assertType('*ERROR*', $a ** $b); + assertType('*ERROR*', $a << $b); + assertType('*ERROR*', $a >> $b); + assertType('bool', $a < $b); + assertType('bool', $a <= $b); + assertType('bool', $a > $b); + assertType('bool', $a >= $b); + assertType('int<-1, 1>', $a <=> $b); + assertType('bool', $a == $b); + assertType('bool', $a != $b); + assertType('*ERROR*', $a & $b); + assertType('*ERROR*', $a ^ $b); + assertType('*ERROR*', $a | $b); + assertType('bool', $a && $b); + assertType('true', $a || $b); + assertType('bool', $a and $b); + assertType('bool', $a xor $b); + assertType('true', $a or $b); + } + + /** @param resource $b */ + public function bcVsResource(Number $a, $b): void + { + assertType('*ERROR*', $a + $b); + assertType('*ERROR*', $a - $b); + assertType('*ERROR*', $a * $b); + assertType('*ERROR*', $a / $b); + assertType('*ERROR*', $a % $b); + assertType('non-empty-string', $a . $b); + assertType('*ERROR*', $a ** $b); + assertType('*ERROR*', $a << $b); + assertType('*ERROR*', $a >> $b); + assertType('bool', $a < $b); + assertType('bool', $a <= $b); + assertType('bool', $a > $b); + assertType('bool', $a >= $b); + assertType('int<-1, 1>', $a <=> $b); + assertType('bool', $a == $b); + assertType('bool', $a != $b); + assertType('*ERROR*', $a & $b); + assertType('*ERROR*', $a ^ $b); + assertType('*ERROR*', $a | $b); + assertType('bool', $a && $b); + assertType('true', $a || $b); + assertType('bool', $a and $b); + assertType('bool', $a xor $b); + assertType('true', $a or $b); + } + + public function bcVsCallable(Number $a, callable $b): void + { + assertType('*ERROR*', $a + $b); + assertType('*ERROR*', $a - $b); + assertType('*ERROR*', $a * $b); + assertType('*ERROR*', $a / $b); + assertType('*ERROR*', $a % $b); + assertType('*ERROR*', $a . $b); + assertType('*ERROR*', $a ** $b); + assertType('*ERROR*', $a << $b); + assertType('*ERROR*', $a >> $b); + assertType('bool', $a < $b); + assertType('bool', $a <= $b); + assertType('bool', $a > $b); + assertType('bool', $a >= $b); + assertType('int<-1, 1>', $a <=> $b); + assertType('bool', $a == $b); + assertType('bool', $a != $b); + assertType('*ERROR*', $a & $b); + assertType('*ERROR*', $a ^ $b); + assertType('*ERROR*', $a | $b); + assertType('bool', $a && $b); + assertType('true', $a || $b); + assertType('bool', $a and $b); + assertType('bool', $a xor $b); + assertType('true', $a or $b); + } + + public function bcVsIterable(Number $a, iterable $b): void + { + assertType('*ERROR*', $a + $b); + assertType('*ERROR*', $a - $b); + assertType('*ERROR*', $a * $b); + assertType('*ERROR*', $a / $b); + assertType('*ERROR*', $a % $b); + assertType('*ERROR*', $a . $b); + assertType('*ERROR*', $a ** $b); + assertType('*ERROR*', $a << $b); + assertType('*ERROR*', $a >> $b); + assertType('bool', $a < $b); + assertType('bool', $a <= $b); + assertType('bool', $a > $b); + assertType('bool', $a >= $b); + assertType('int<-1, 1>', $a <=> $b); + assertType('bool', $a == $b); + assertType('bool', $a != $b); + assertType('*ERROR*', $a & $b); + assertType('*ERROR*', $a ^ $b); + assertType('*ERROR*', $a | $b); + assertType('bool', $a && $b); + assertType('bool', $a || $b); + assertType('bool', $a and $b); + assertType('bool', $a xor $b); + assertType('bool', $a or $b); + } + + public function bcVsStringable(Number $a, \Stringable $b): void + { + assertType('*ERROR*', $a + $b); + assertType('*ERROR*', $a - $b); + assertType('*ERROR*', $a * $b); + assertType('*ERROR*', $a / $b); + assertType('*ERROR*', $a % $b); + assertType('non-empty-string', $a . $b); + assertType('*ERROR*', $a ** $b); + assertType('*ERROR*', $a << $b); + assertType('*ERROR*', $a >> $b); + assertType('bool', $a < $b); + assertType('bool', $a <= $b); + assertType('bool', $a > $b); + assertType('bool', $a >= $b); + assertType('int<-1, 1>', $a <=> $b); + assertType('bool', $a == $b); + assertType('bool', $a != $b); + assertType('*ERROR*', $a & $b); + assertType('*ERROR*', $a ^ $b); + assertType('*ERROR*', $a | $b); + assertType('bool', $a && $b); + assertType('true', $a || $b); + assertType('bool', $a and $b); + assertType('bool', $a xor $b); + assertType('true', $a or $b); + } + + public function bcVsNever(Number $a): void + { + for ($b = 1; $b < count([]); $b++) { + assertType('*NEVER*', $a + $b); + assertType('*ERROR*', $a - $b); // Inconsistency: getPlusType handles never types right at the beginning, getMinusType doesn't. + assertType('*ERROR*', $a * $b); + assertType('*ERROR*', $a / $b); + assertType('*NEVER*', $a % $b); + assertType('non-empty-string&numeric-string', $a . $b); + assertType('*ERROR*', $a ** $b); + assertType('*NEVER*', $a << $b); + assertType('*NEVER*', $a >> $b); + assertType('bool', $a < $b); + assertType('bool', $a <= $b); + assertType('bool', $a > $b); + assertType('bool', $a >= $b); + assertType('*NEVER*', $a <=> $b); + assertType('bool', $a == $b); + assertType('bool', $a != $b); + assertType('*NEVER*', $a & $b); + assertType('*NEVER*', $a ^ $b); + assertType('*NEVER*', $a | $b); + assertType('bool', $a && $b); + assertType('bool', $a || $b); + assertType('bool', $a and $b); + assertType('bool', $a xor $b); + assertType('bool', $a or $b); + } + } +} From b260a9e3beabca5756ef71dd29c8174b878a0e9b Mon Sep 17 00:00:00 2001 From: schlndh Date: Sun, 2 Mar 2025 11:13:22 +0100 Subject: [PATCH 2/3] remove useless test --- .../Analyser/NodeScopeResolverTest.php | 4 - .../data => Analyser/nsrt}/bcmath-number.php | 0 .../InvalidBinaryOperationRuleTest.php | 522 ------------------ 3 files changed, 526 deletions(-) rename tests/PHPStan/{Rules/Operators/data => Analyser/nsrt}/bcmath-number.php (100%) diff --git a/tests/PHPStan/Analyser/NodeScopeResolverTest.php b/tests/PHPStan/Analyser/NodeScopeResolverTest.php index 5a0ad0f06d..7f3d9638b2 100644 --- a/tests/PHPStan/Analyser/NodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/NodeScopeResolverTest.php @@ -196,10 +196,6 @@ private static function findTestFiles(): iterable yield __DIR__ . '/../Rules/Comparison/data/bug-9499.php'; } - if (PHP_VERSION_ID >= 80400) { - yield __DIR__ . '/../Rules/Operators/data/bcmath-number.php'; - } - yield __DIR__ . '/../Rules/PhpDoc/data/bug-8609-function.php'; yield __DIR__ . '/../Rules/Comparison/data/bug-5365.php'; yield __DIR__ . '/../Rules/Comparison/data/bug-6551.php'; diff --git a/tests/PHPStan/Rules/Operators/data/bcmath-number.php b/tests/PHPStan/Analyser/nsrt/bcmath-number.php similarity index 100% rename from tests/PHPStan/Rules/Operators/data/bcmath-number.php rename to tests/PHPStan/Analyser/nsrt/bcmath-number.php diff --git a/tests/PHPStan/Rules/Operators/InvalidBinaryOperationRuleTest.php b/tests/PHPStan/Rules/Operators/InvalidBinaryOperationRuleTest.php index 64b27ccb21..135194070b 100644 --- a/tests/PHPStan/Rules/Operators/InvalidBinaryOperationRuleTest.php +++ b/tests/PHPStan/Rules/Operators/InvalidBinaryOperationRuleTest.php @@ -303,528 +303,6 @@ public function testBug5309(): void $this->analyse([__DIR__ . '/data/bug-5309.php'], []); } - public function testBcMathNumber(): void - { - if (PHP_VERSION_ID < 80400) { - self::markTestSkipped('Test requires PHP 8.4.'); - } - - $this->analyse([__DIR__ . '/data/bcmath-number.php'], [ - [ - 'Binary operation "<<" between BcMath\\Number and BcMath\\Number results in an error.', - 19, - ], - [ - 'Binary operation ">>" between BcMath\\Number and BcMath\\Number results in an error.', - 20, - ], - [ - 'Binary operation "&" between BcMath\\Number and BcMath\\Number results in an error.', - 28, - ], - [ - 'Binary operation "^" between BcMath\\Number and BcMath\\Number results in an error.', - 29, - ], - [ - 'Binary operation "|" between BcMath\\Number and BcMath\\Number results in an error.', - 30, - ], - [ - 'Binary operation "<<" between BcMath\\Number and int results in an error.', - 47, - ], - [ - 'Binary operation ">>" between BcMath\\Number and int results in an error.', - 48, - ], - [ - 'Binary operation "&" between BcMath\\Number and int results in an error.', - 56, - ], - [ - 'Binary operation "^" between BcMath\\Number and int results in an error.', - 57, - ], - [ - 'Binary operation "|" between BcMath\\Number and int results in an error.', - 58, - ], - [ - 'Binary operation "+" between BcMath\\Number and float results in an error.', - 68, - ], - [ - 'Binary operation "-" between BcMath\\Number and float results in an error.', - 69, - ], - [ - 'Binary operation "*" between BcMath\\Number and float results in an error.', - 70, - ], - [ - 'Binary operation "/" between BcMath\\Number and float results in an error.', - 71, - ], - [ - 'Binary operation "%" between BcMath\\Number and float results in an error.', - 72, - ], - [ - 'Binary operation "**" between BcMath\\Number and float results in an error.', - 74, - ], - [ - 'Binary operation "<<" between BcMath\\Number and float results in an error.', - 75, - ], - [ - 'Binary operation ">>" between BcMath\\Number and float results in an error.', - 76, - ], - [ - 'Binary operation "&" between BcMath\\Number and float results in an error.', - 84, - ], - [ - 'Binary operation "^" between BcMath\\Number and float results in an error.', - 85, - ], - [ - 'Binary operation "|" between BcMath\\Number and float results in an error.', - 86, - ], - [ - 'Binary operation "<<" between BcMath\\Number and numeric-string results in an error.', - 104, - ], - [ - 'Binary operation ">>" between BcMath\\Number and numeric-string results in an error.', - 105, - ], - [ - 'Binary operation "&" between BcMath\\Number and numeric-string results in an error.', - 113, - ], - [ - 'Binary operation "^" between BcMath\\Number and numeric-string results in an error.', - 114, - ], - [ - 'Binary operation "|" between BcMath\\Number and numeric-string results in an error.', - 115, - ], - [ - 'Binary operation "+" between BcMath\\Number and string results in an error.', - 125, - ], - [ - 'Binary operation "-" between BcMath\\Number and string results in an error.', - 126, - ], - [ - 'Binary operation "*" between BcMath\\Number and string results in an error.', - 127, - ], - [ - 'Binary operation "/" between BcMath\\Number and string results in an error.', - 128, - ], - [ - 'Binary operation "%" between BcMath\\Number and string results in an error.', - 129, - ], - [ - 'Binary operation "**" between BcMath\\Number and string results in an error.', - 131, - ], - [ - 'Binary operation "<<" between BcMath\\Number and string results in an error.', - 132, - ], - [ - 'Binary operation ">>" between BcMath\\Number and string results in an error.', - 133, - ], - [ - 'Binary operation "&" between BcMath\\Number and string results in an error.', - 141, - ], - [ - 'Binary operation "^" between BcMath\\Number and string results in an error.', - 142, - ], - [ - 'Binary operation "|" between BcMath\\Number and string results in an error.', - 143, - ], - [ - 'Binary operation "+" between BcMath\\Number and bool results in an error.', - 153, - ], - [ - 'Binary operation "-" between BcMath\\Number and bool results in an error.', - 154, - ], - [ - 'Binary operation "*" between BcMath\\Number and bool results in an error.', - 155, - ], - [ - 'Binary operation "/" between BcMath\\Number and bool results in an error.', - 156, - ], - [ - 'Binary operation "%" between BcMath\\Number and bool results in an error.', - 157, - ], - [ - 'Binary operation "**" between BcMath\\Number and bool results in an error.', - 159, - ], - [ - 'Binary operation "<<" between BcMath\\Number and bool results in an error.', - 160, - ], - [ - 'Binary operation ">>" between BcMath\\Number and bool results in an error.', - 161, - ], - [ - 'Binary operation "&" between BcMath\\Number and bool results in an error.', - 169, - ], - [ - 'Binary operation "^" between BcMath\\Number and bool results in an error.', - 170, - ], - [ - 'Binary operation "|" between BcMath\\Number and bool results in an error.', - 171, - ], - [ - 'Binary operation "+" between BcMath\\Number and null results in an error.', - 182, - ], - [ - 'Binary operation "-" between BcMath\\Number and null results in an error.', - 183, - ], - [ - 'Binary operation "/" between BcMath\\Number and null results in an error.', - 185, - ], - [ - 'Binary operation "%" between BcMath\\Number and null results in an error.', - 186, - ], - [ - 'Binary operation "**" between BcMath\\Number and null results in an error.', - 188, - ], - [ - 'Binary operation "<<" between BcMath\\Number and null results in an error.', - 189, - ], - [ - 'Binary operation ">>" between BcMath\\Number and null results in an error.', - 190, - ], - [ - 'Binary operation "&" between BcMath\\Number and null results in an error.', - 198, - ], - [ - 'Binary operation "^" between BcMath\\Number and null results in an error.', - 199, - ], - [ - 'Binary operation "|" between BcMath\\Number and null results in an error.', - 200, - ], - [ - 'Binary operation "+" between BcMath\\Number and array results in an error.', - 210, - ], - [ - 'Binary operation "-" between BcMath\\Number and array results in an error.', - 211, - ], - [ - 'Binary operation "*" between BcMath\\Number and array results in an error.', - 212, - ], - [ - 'Binary operation "/" between BcMath\\Number and array results in an error.', - 213, - ], - [ - 'Binary operation "%" between BcMath\\Number and array results in an error.', - 214, - ], - [ - 'Binary operation "." between BcMath\\Number and array results in an error.', - 215, - ], - [ - 'Binary operation "**" between BcMath\\Number and array results in an error.', - 216, - ], - [ - 'Binary operation "<<" between BcMath\\Number and array results in an error.', - 217, - ], - [ - 'Binary operation ">>" between BcMath\\Number and array results in an error.', - 218, - ], - [ - 'Binary operation "&" between BcMath\\Number and array results in an error.', - 226, - ], - [ - 'Binary operation "^" between BcMath\\Number and array results in an error.', - 227, - ], - [ - 'Binary operation "|" between BcMath\\Number and array results in an error.', - 228, - ], - [ - 'Binary operation "+" between BcMath\\Number and object results in an error.', - 238, - ], - [ - 'Binary operation "-" between BcMath\\Number and object results in an error.', - 239, - ], - [ - 'Binary operation "*" between BcMath\\Number and object results in an error.', - 240, - ], - [ - 'Binary operation "/" between BcMath\\Number and object results in an error.', - 241, - ], - [ - 'Binary operation "%" between BcMath\\Number and object results in an error.', - 242, - ], - [ - 'Binary operation "." between BcMath\\Number and object results in an error.', - 243, - ], - [ - 'Binary operation "**" between BcMath\\Number and object results in an error.', - 244, - ], - [ - 'Binary operation "<<" between BcMath\\Number and object results in an error.', - 245, - ], - [ - 'Binary operation ">>" between BcMath\\Number and object results in an error.', - 246, - ], - [ - 'Binary operation "&" between BcMath\\Number and object results in an error.', - 254, - ], - [ - 'Binary operation "^" between BcMath\\Number and object results in an error.', - 255, - ], - [ - 'Binary operation "|" between BcMath\\Number and object results in an error.', - 256, - ], - [ - 'Binary operation "+" between BcMath\\Number and resource results in an error.', - 267, - ], - [ - 'Binary operation "-" between BcMath\\Number and resource results in an error.', - 268, - ], - [ - 'Binary operation "*" between BcMath\\Number and resource results in an error.', - 269, - ], - [ - 'Binary operation "/" between BcMath\\Number and resource results in an error.', - 270, - ], - [ - 'Binary operation "%" between BcMath\\Number and resource results in an error.', - 271, - ], - [ - 'Binary operation "**" between BcMath\\Number and resource results in an error.', - 273, - ], - [ - 'Binary operation "<<" between BcMath\\Number and resource results in an error.', - 274, - ], - [ - 'Binary operation ">>" between BcMath\\Number and resource results in an error.', - 275, - ], - [ - 'Binary operation "&" between BcMath\\Number and resource results in an error.', - 283, - ], - [ - 'Binary operation "^" between BcMath\\Number and resource results in an error.', - 284, - ], - [ - 'Binary operation "|" between BcMath\\Number and resource results in an error.', - 285, - ], - [ - 'Binary operation "+" between BcMath\\Number and callable(): mixed results in an error.', - 295, - ], - [ - 'Binary operation "-" between BcMath\\Number and callable(): mixed results in an error.', - 296, - ], - [ - 'Binary operation "*" between BcMath\\Number and callable(): mixed results in an error.', - 297, - ], - [ - 'Binary operation "/" between BcMath\\Number and callable(): mixed results in an error.', - 298, - ], - [ - 'Binary operation "%" between BcMath\\Number and callable(): mixed results in an error.', - 299, - ], - [ - 'Binary operation "." between BcMath\\Number and callable(): mixed results in an error.', - 300, - ], - [ - 'Binary operation "**" between BcMath\\Number and callable(): mixed results in an error.', - 301, - ], - [ - 'Binary operation "<<" between BcMath\\Number and callable(): mixed results in an error.', - 302, - ], - [ - 'Binary operation ">>" between BcMath\\Number and callable(): mixed results in an error.', - 303, - ], - [ - 'Binary operation "&" between BcMath\\Number and callable(): mixed results in an error.', - 311, - ], - [ - 'Binary operation "^" between BcMath\\Number and callable(): mixed results in an error.', - 312, - ], - [ - 'Binary operation "|" between BcMath\\Number and callable(): mixed results in an error.', - 313, - ], - [ - 'Binary operation "+" between BcMath\\Number and iterable results in an error.', - 323, - ], - [ - 'Binary operation "-" between BcMath\\Number and iterable results in an error.', - 324, - ], - [ - 'Binary operation "*" between BcMath\\Number and iterable results in an error.', - 325, - ], - [ - 'Binary operation "/" between BcMath\\Number and iterable results in an error.', - 326, - ], - [ - 'Binary operation "%" between BcMath\\Number and iterable results in an error.', - 327, - ], - [ - 'Binary operation "." between BcMath\\Number and iterable results in an error.', - 328, - ], - [ - 'Binary operation "**" between BcMath\\Number and iterable results in an error.', - 329, - ], - [ - 'Binary operation "<<" between BcMath\\Number and iterable results in an error.', - 330, - ], - [ - 'Binary operation ">>" between BcMath\\Number and iterable results in an error.', - 331, - ], - [ - 'Binary operation "&" between BcMath\\Number and iterable results in an error.', - 339, - ], - [ - 'Binary operation "^" between BcMath\\Number and iterable results in an error.', - 340, - ], - [ - 'Binary operation "|" between BcMath\\Number and iterable results in an error.', - 341, - ], - [ - 'Binary operation "+" between BcMath\\Number and Stringable results in an error.', - 351, - ], - [ - 'Binary operation "-" between BcMath\\Number and Stringable results in an error.', - 352, - ], - [ - 'Binary operation "*" between BcMath\\Number and Stringable results in an error.', - 353, - ], - [ - 'Binary operation "/" between BcMath\\Number and Stringable results in an error.', - 354, - ], - [ - 'Binary operation "%" between BcMath\\Number and Stringable results in an error.', - 355, - ], - [ - 'Binary operation "**" between BcMath\\Number and Stringable results in an error.', - 357, - ], - [ - 'Binary operation "<<" between BcMath\\Number and Stringable results in an error.', - 358, - ], - [ - 'Binary operation ">>" between BcMath\\Number and Stringable results in an error.', - 359, - ], - [ - 'Binary operation "&" between BcMath\\Number and Stringable results in an error.', - 367, - ], - [ - 'Binary operation "^" between BcMath\\Number and Stringable results in an error.', - 368, - ], - [ - 'Binary operation "|" between BcMath\\Number and Stringable results in an error.', - 369, - ], - ]); - } - public function testBinaryMixed(): void { if (PHP_VERSION_ID < 80000) { From 5f9560b5043164c9a13471c73b6095ccd3e4eddd Mon Sep 17 00:00:00 2001 From: schlndh Date: Sun, 2 Mar 2025 11:18:46 +0100 Subject: [PATCH 3/3] fix lint directive for NSRT --- tests/PHPStan/Analyser/nsrt/bcmath-number.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/PHPStan/Analyser/nsrt/bcmath-number.php b/tests/PHPStan/Analyser/nsrt/bcmath-number.php index 361ca4b275..2bdd9611b4 100644 --- a/tests/PHPStan/Analyser/nsrt/bcmath-number.php +++ b/tests/PHPStan/Analyser/nsrt/bcmath-number.php @@ -1,4 +1,6 @@ -= 8.4 += 8.4 + +declare(strict_types = 1); namespace BcMathNumber;