From 0b9da26ba77cb1f576b9ca61c26f2d15c7d81d60 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 384b945d17..72460b86ba 100644 --- a/src/Reflection/InitializerExprTypeResolver.php +++ b/src/Reflection/InitializerExprTypeResolver.php @@ -2594,8 +2594,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 64dba66c259a0fd2156aa459dfb580d3e779dbac 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 72460b86ba..eae5158b7e 100644 --- a/src/Reflection/InitializerExprTypeResolver.php +++ b/src/Reflection/InitializerExprTypeResolver.php @@ -2595,7 +2595,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 386d808a8792f3d67e4f3c572c56717eeb9fa27d 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/Generator/data/gnsr.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/PHPStan/Analyser/Generator/data/gnsr.php b/tests/PHPStan/Analyser/Generator/data/gnsr.php index c6bddf33ff..99636621b2 100644 --- a/tests/PHPStan/Analyser/Generator/data/gnsr.php +++ b/tests/PHPStan/Analyser/Generator/data/gnsr.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); }