Repository navigation
Read the updated value of consumed prefix mutations - #6692
Conversation
|
CI follow-up: the core tests and static analysis pass. I reproduced Larastan's two failures with both the base and PR PHARs (1,526 tests / 1,868 assertions each). All 12 failing-job diagnostics also match #6691 on the same base; the PHP 8.6 extension jobs fail during Composer resolution. No patch regression is evident, so I've kept this fix focused. |
| $assignedScope, | ||
| beforeScope: $scope, | ||
| expr: $expr, | ||
| variableFlow: VariableFlow::sequence($varResult->getVariableFlow(), $valueFlowWrite !== null && $context->isValueConsumed() ? VariableFlow::inputs($valueFlowWrite->getId(), $context->getValueFlowTarget() !== null ? $context->getValueFlowTarget()->getId() : null) : null, VariableFlowBuilder::targetWrite($expr->var, VariableWrite::KIND_PRE_DEC, $assignedScope, $storage)), |
There was a problem hiding this comment.
maybe there is some code-style rule we could enforce so such long expressions will be split over more lines by default - which would ease reading diffs in such lines (separate PR)
There was a problem hiding this comment.
Thanks for reviewing! Agreed, a separate formatting-rule PR would keep this fix focused and make future diffs easier to read.
|
//cc @SanderMuller |
SanderMuller
left a comment
There was a problem hiding this comment.
I reviewed this at f4a22bc21 against its base f9a915969, and it fixes phpstan/phpstan#15411 without hiding real unused writes.
The reporter's snippet, at level 10 with bleedingEdge, reports preInc.unused on the base and nothing with this PR. var_dump(++$c) and if (++$c > 3) had the same false positive, and both are fixed too.
These are still reported, the same as on the base:
- a bare
++$c;and--$c; - a second
++$cafter$y = ++$c, when only$yis read return $c++;(postInc.unused)- an unused
++$a['x']
One result changes, and I think the new one is right. $x = ++$c; return 1; now reports only Variable $x is never read, not also the ++, because the new value goes into $x.
testBug15411 fails with the src changes reverted and passes with them. The full suite passes with and without the turbo extension (22503 tests, 74 skipped). make phpstan reports no errors, and phpcs passes on the touched files.
Turbo: the strict build has no compiler warnings, smoke.php reports ALL OK, and signature-parity.php reports OK. The raw output is identical with and without the extension. I compared my probe file plus the new test data, and src/Analyser plus the dead-code test data. With only the .cpp/.h changes reverted, the turbo build still reports the three false positives, so the port is needed. The C++ builds the target read before the target write, but targetRead() for a variable only builds value objects, and the output matches.
Performance: I ran a cold bin/phpstan analyse src/Type src/Analyser with bleedingEdge and without turbo, 3 interleaved runs. The base took 6.83-7.54 s and 56.2-57.2 s user CPU, and this PR took 6.90-6.99 s and 56.6-57.1 s. The output is identical.
CI: the red checks are the same set as on #6690, which has the same base. I compared the error output of the Rector, Larastan, laravel/framework, magento and shopware jobs between the two PRs, and it is identical. The same holds for the 8.6 nette and phpunit make phpstan jobs.
|
thank you! |
Prefix increment/decrement expressions evaluate to the updated value. Their variable flow currently records only consumption of the mutation's inputs, leaving the new write marked unused even when it is returned, such as
return (string) ++$count.Record a target read after the prefix write, preserving the enclosing value-flow target. This also covers consumed array-offset mutations. Postfix expressions keep their existing pre-mutation input flow, and genuinely unused mutation results remain diagnosed. Mirror the change in the native handlers and bump the expected Turbo version.
Closes phpstan/phpstan#15411.
The regression retains the reported reproducer and covers decrement, assignment to a used result and array offsets. It fails with six unused-value diagnostics before the fix and passes after it.
Validation
UnusedVariableRuleTest: 33 tests / 33 assertions, with and without Turbo; includes existing unused prefix/postfix controls.ALL OK) and method/declaration parity on PHP 8.3 pass.Reproduce the rule regression with
php vendor/bin/phpunit tests/PHPStan/Rules/DeadCode/UnusedVariableRuleTest.php --filter testBug15411.