From 47ff1064f3340f8e7f0745d6929e4c8dd101332d Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Mon, 13 Oct 2025 21:04:05 +0200 Subject: [PATCH 1/3] Resolve bitwise not on constant integer --- src/Reflection/InitializerExprTypeResolver.php | 5 ++++- tests/PHPStan/Analyser/nsrt/bitwise-not.php | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Reflection/InitializerExprTypeResolver.php b/src/Reflection/InitializerExprTypeResolver.php index c76661d6d2..1d0417b720 100644 --- a/src/Reflection/InitializerExprTypeResolver.php +++ b/src/Reflection/InitializerExprTypeResolver.php @@ -2630,8 +2630,11 @@ public function getBitwiseNotTypeFromType(Type $exprType): Type return TypeCombinator::intersect(...$accessories); } + if ($type instanceof ConstantIntegerType || $type instanceof ConstantFloatType) { + return new ConstantIntegerType(~$type->getValue()); + } if ($type->isInteger()->yes() || $type->isFloat()->yes()) { - return new IntegerType(); //no const types here, result depends on PHP_INT_SIZE + return new IntegerType(); } return new ErrorType(); }); diff --git a/tests/PHPStan/Analyser/nsrt/bitwise-not.php b/tests/PHPStan/Analyser/nsrt/bitwise-not.php index 37c29f8f97..01623d2d5b 100644 --- a/tests/PHPStan/Analyser/nsrt/bitwise-not.php +++ b/tests/PHPStan/Analyser/nsrt/bitwise-not.php @@ -17,5 +17,5 @@ function foo(int $int, string $string, float $float, $stringOrInt, string $nonEm assertType('int', ~$float); assertType('int|string', ~$stringOrInt); assertType("'" . (~"abc") . "'", ~"abc"); - assertType('int', ~1); //result is dependent on PHP_INT_SIZE + assertType('-2', ~1); } From 321d0043e361c8fac3729d0677db197ee5a9a9a1 Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Mon, 13 Oct 2025 21:34:45 +0200 Subject: [PATCH 2/3] Fix deprecation --- src/Reflection/InitializerExprTypeResolver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Reflection/InitializerExprTypeResolver.php b/src/Reflection/InitializerExprTypeResolver.php index 1d0417b720..32077bbd69 100644 --- a/src/Reflection/InitializerExprTypeResolver.php +++ b/src/Reflection/InitializerExprTypeResolver.php @@ -2631,7 +2631,7 @@ public function getBitwiseNotTypeFromType(Type $exprType): Type return TypeCombinator::intersect(...$accessories); } if ($type instanceof ConstantIntegerType || $type instanceof ConstantFloatType) { - return new ConstantIntegerType(~$type->getValue()); + return new ConstantIntegerType(~ (int) $type->getValue()); } if ($type->isInteger()->yes() || $type->isFloat()->yes()) { return new IntegerType(); From dac0defed278ca4a21636c384ccf0d718a9e81d6 Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Fri, 5 Dec 2025 16:56:03 +0100 Subject: [PATCH 3/3] Fix --- tests/PHPStan/Analyser/Fiber/data/fnsr.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/PHPStan/Analyser/Fiber/data/fnsr.php b/tests/PHPStan/Analyser/Fiber/data/fnsr.php index e56837adcf..ccfeaa3e85 100644 --- a/tests/PHPStan/Analyser/Fiber/data/fnsr.php +++ b/tests/PHPStan/Analyser/Fiber/data/fnsr.php @@ -96,8 +96,8 @@ public function doBitwiseNot($a, int $b): void { assertType('int', ~$a); assertNativeType('int', ~$b); - assertType('int', ~1); - assertNativeType('int', ~1); + assertType('-2', ~1); + assertNativeType('-2', ~1); assertType('int', ~$b); assertNativeType('int', ~$b); }