From 5bdfa788d65ae5f9259c516f2dff99f39ec65871 Mon Sep 17 00:00:00 2001 From: Alfred Bez <1001186+alfredbez@users.noreply.github.com> Date: Fri, 16 Oct 2026 13:14:16 +0000 Subject: [PATCH] Fix false-positive unused-variable in declare() {} block Fixes https://github.com/phpstan/phpstan/issues/15394 --- src/Analyser/StmtHandler/DeclareHandler.php | 4 ++- .../Rules/DeadCode/UnusedVariableRuleTest.php | 7 +++++ .../PHPStan/Rules/DeadCode/data/bug-15394.php | 26 +++++++++++++++++++ turbo-ext/src/DeclareHandler.cpp | 6 +++-- 4 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 tests/PHPStan/Rules/DeadCode/data/bug-15394.php diff --git a/src/Analyser/StmtHandler/DeclareHandler.php b/src/Analyser/StmtHandler/DeclareHandler.php index 25518f529e8..ba23ddcaf79 100644 --- a/src/Analyser/StmtHandler/DeclareHandler.php +++ b/src/Analyser/StmtHandler/DeclareHandler.php @@ -60,6 +60,7 @@ public function processStmt( $scope = $scope->enterDeclareStrictTypes(); } + $variableFlow = null; if ($stmt->stmts !== null) { $result = $nodeScopeResolver->processStmtNodesInternal($stmt, $stmt->stmts, $scope, $storage, $nodeCallback, $context); $dependencies[] = $result->getDependencies(); @@ -69,9 +70,10 @@ public function processStmt( $impurePoints = $result->getImpurePoints(); $alwaysTerminating = $result->isAlwaysTerminating(); $exitPoints = $result->getExitPoints(); + $variableFlow = $result->getVariableFlow(); } - return new InternalStatementResult($scope, hasYield: $hasYield, isAlwaysTerminating: $alwaysTerminating, exitPoints: $exitPoints, throwPoints: $throwPoints, impurePoints: $impurePoints, dependencies: Dependencies::merge(...$dependencies)); + return new InternalStatementResult($scope, hasYield: $hasYield, isAlwaysTerminating: $alwaysTerminating, exitPoints: $exitPoints, throwPoints: $throwPoints, impurePoints: $impurePoints, variableFlow: $variableFlow, dependencies: Dependencies::merge(...$dependencies)); } } diff --git a/tests/PHPStan/Rules/DeadCode/UnusedVariableRuleTest.php b/tests/PHPStan/Rules/DeadCode/UnusedVariableRuleTest.php index 2ceca6991c7..e23f4137eec 100644 --- a/tests/PHPStan/Rules/DeadCode/UnusedVariableRuleTest.php +++ b/tests/PHPStan/Rules/DeadCode/UnusedVariableRuleTest.php @@ -459,6 +459,13 @@ public function testBug15225(): void $this->analyse([__DIR__ . '/data/bug-15225.php'], []); } + public function testBug15394(): void + { + $this->analyse([__DIR__ . '/data/bug-15394.php'], [ + ['Variable $z is never read.', 24], + ]); + } + public function testFlowMessages(): void { $this->analyse([__DIR__ . '/data/unused-variable-flow-messages.php'], [ diff --git a/tests/PHPStan/Rules/DeadCode/data/bug-15394.php b/tests/PHPStan/Rules/DeadCode/data/bug-15394.php new file mode 100644 index 00000000000..bd926537066 --- /dev/null +++ b/tests/PHPStan/Rules/DeadCode/data/bug-15394.php @@ -0,0 +1,26 @@ +