From 9cc0922aa45d68aff6e9eaf926291ef1c7aeb9b7 Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Sat, 9 Aug 2025 16:04:04 +0200 Subject: [PATCH 1/2] Consider assert as side effect --- ...unctionStatementWithoutSideEffectsRule.php | 4 +++ ...oMethodStatementWithoutSideEffectsRule.php | 3 ++ ...cMethodStatementWithoutSideEffectsRule.php | 4 +++ ...ionStatementWithoutSideEffectsRuleTest.php | 5 +++ .../Rules/Functions/data/bug-12224.php | 19 ++++++++++ ...hodStatementWithoutSideEffectsRuleTest.php | 5 +++ ...hodStatementWithoutSideEffectsRuleTest.php | 5 +++ .../PHPStan/Rules/Methods/data/bug-12224.php | 35 +++++++++++++++++++ 8 files changed, 80 insertions(+) create mode 100644 tests/PHPStan/Rules/Functions/data/bug-12224.php create mode 100644 tests/PHPStan/Rules/Methods/data/bug-12224.php diff --git a/src/Rules/Functions/CallToFunctionStatementWithoutSideEffectsRule.php b/src/Rules/Functions/CallToFunctionStatementWithoutSideEffectsRule.php index e7d9c46156..9a915f664b 100644 --- a/src/Rules/Functions/CallToFunctionStatementWithoutSideEffectsRule.php +++ b/src/Rules/Functions/CallToFunctionStatementWithoutSideEffectsRule.php @@ -65,6 +65,10 @@ public function processNode(Node $node, Scope $scope): array } $function = $this->reflectionProvider->getFunction($funcCall->name, $scope); + if (count($function->getAsserts()->getAsserts()) > 0) { + return []; + } + $functionName = $function->getName(); $functionHasSideEffects = !$function->hasSideEffects()->no(); diff --git a/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php b/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php index 9b6adbdd14..0db3853743 100644 --- a/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php +++ b/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php @@ -69,6 +69,9 @@ public function processNode(Node $node, Scope $scope): array } $method = $calledOnType->getMethod($methodName, $scope); + if (count($method->getAsserts()->getAsserts()) > 0) { + return []; + } return [ RuleErrorBuilder::message(sprintf( diff --git a/src/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRule.php b/src/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRule.php index 31dc4dd096..6872f5604e 100644 --- a/src/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRule.php +++ b/src/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRule.php @@ -87,6 +87,10 @@ public function processNode(Node $node, Scope $scope): array return []; } + if (count($method->getAsserts()->getAsserts()) > 0) { + return []; + } + $methodResult = $scope->getType($staticCall); if ($methodResult instanceof NeverType && $methodResult->isExplicit()) { return []; diff --git a/tests/PHPStan/Rules/Functions/CallToFunctionStatementWithoutSideEffectsRuleTest.php b/tests/PHPStan/Rules/Functions/CallToFunctionStatementWithoutSideEffectsRuleTest.php index 28257e5a80..6d2fe2bbba 100644 --- a/tests/PHPStan/Rules/Functions/CallToFunctionStatementWithoutSideEffectsRuleTest.php +++ b/tests/PHPStan/Rules/Functions/CallToFunctionStatementWithoutSideEffectsRuleTest.php @@ -85,6 +85,11 @@ public function testPhpDoc(): void ]); } + public function testBug12224(): void + { + $this->analyse([__DIR__ . '/data/bug-12224.php'], []); + } + public function testBug4455(): void { require_once __DIR__ . '/data/bug-4455.php'; diff --git a/tests/PHPStan/Rules/Functions/data/bug-12224.php b/tests/PHPStan/Rules/Functions/data/bug-12224.php new file mode 100644 index 0000000000..9970576bca --- /dev/null +++ b/tests/PHPStan/Rules/Functions/data/bug-12224.php @@ -0,0 +1,19 @@ +analyse([__DIR__ . '/data/bug-11503.php'], $errors); } + public function testBug12224(): void + { + $this->analyse([__DIR__ . '/data/bug-12224.php'], []); + } + public function testFirstClassCallables(): void { $this->analyse([__DIR__ . '/data/first-class-callable-method-without-side-effect.php'], [ diff --git a/tests/PHPStan/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRuleTest.php b/tests/PHPStan/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRuleTest.php index bec56ff7d6..96dda15501 100644 --- a/tests/PHPStan/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRuleTest.php +++ b/tests/PHPStan/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRuleTest.php @@ -70,6 +70,11 @@ public function testBug4455(): void $this->analyse([__DIR__ . '/data/bug-4455-static.php'], []); } + public function testBug12224(): void + { + $this->analyse([__DIR__ . '/data/bug-12224.php'], []); + } + public function testFirstClassCallables(): void { $this->analyse([__DIR__ . '/data/first-class-callable-static-method-without-side-effect.php'], [ diff --git a/tests/PHPStan/Rules/Methods/data/bug-12224.php b/tests/PHPStan/Rules/Methods/data/bug-12224.php new file mode 100644 index 0000000000..70664fee05 --- /dev/null +++ b/tests/PHPStan/Rules/Methods/data/bug-12224.php @@ -0,0 +1,35 @@ +string($a); From a3b003747b261385dfefe0e475fef091d2e6e426 Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Sat, 9 Aug 2025 16:10:51 +0200 Subject: [PATCH 2/2] Fix cs --- .../Functions/CallToFunctionStatementWithoutSideEffectsRule.php | 1 + .../Methods/CallToMethodStatementWithoutSideEffectsRule.php | 1 + .../CallToStaticMethodStatementWithoutSideEffectsRule.php | 1 + 3 files changed, 3 insertions(+) diff --git a/src/Rules/Functions/CallToFunctionStatementWithoutSideEffectsRule.php b/src/Rules/Functions/CallToFunctionStatementWithoutSideEffectsRule.php index 9a915f664b..a117c228fd 100644 --- a/src/Rules/Functions/CallToFunctionStatementWithoutSideEffectsRule.php +++ b/src/Rules/Functions/CallToFunctionStatementWithoutSideEffectsRule.php @@ -11,6 +11,7 @@ use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Type\NeverType; use PHPStan\Type\Type; +use function count; use function in_array; use function sprintf; diff --git a/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php b/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php index 0db3853743..e0a99028c2 100644 --- a/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php +++ b/src/Rules/Methods/CallToMethodStatementWithoutSideEffectsRule.php @@ -13,6 +13,7 @@ use PHPStan\Type\ErrorType; use PHPStan\Type\NeverType; use PHPStan\Type\Type; +use function count; use function sprintf; /** diff --git a/src/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRule.php b/src/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRule.php index 6872f5604e..2c80a25856 100644 --- a/src/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRule.php +++ b/src/Rules/Methods/CallToStaticMethodStatementWithoutSideEffectsRule.php @@ -15,6 +15,7 @@ use PHPStan\Type\NeverType; use PHPStan\Type\ObjectType; use PHPStan\Type\Type; +use function count; use function sprintf; use function strtolower;