Detect private promoted properties whose only reads are self-writes via new self()#5599
Conversation
…ia `new self()` - Track whether each property read is a "true read" vs a "self-write" (property passed to the same constructor parameter of the same class) - After processing all usages, if a promoted property's only reads are self-writes, mark it as unread so the "never read, only written" error is reported - Handles new self(), new static(), and new ClassName() for the same class - Named arguments are correctly matched by parameter name - Properties passed to different parameters or different classes are not affected - Add baseline entries for 3 new findings in PHPStan's own code
ondrejmirtes
left a comment
There was a problem hiding this comment.
Instead of baselining the PHPStan errors, please actually fix them by removing the promoted properties.
…dPropertyPrototypeReflection Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…elper Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Done. I addressed the review by removing the unused promoted properties instead of baselining them:
Both |
ondrejmirtes
left a comment
There was a problem hiding this comment.
Make sure there are no edits to the baseline file. You've left an empty newline.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Done. Removed the stray blank line from |
Summary
Detects when a private promoted property is only ever "read" in order to pass its value to the same constructor parameter of the same class (e.g.
return new self($this->test)). In such cases, the property is effectively only writing to itself and should be reported as "never read, only written."Changes
src/Rules/DeadCode/UnusedPrivatePropertyRule.php:hasTrueReadtracking field to distinguish genuine reads from self-writesreadflag clearedisPropertySelfWrite()helper that usesScope::getFunctionCallStackWithParameters()to check if a read occurs inside a constructor call of the same class, targeting the same-named parametertests/PHPStan/Rules/DeadCode/data/bug-14573.phpwith comprehensive test casestestBug14573toUnusedPrivatePropertyRuleTestRoot cause
The
UnusedPrivatePropertyRulepreviously treated anyPropertyReadas evidence that a property is used. However, when a promoted property's only reads are passing its value tonew self(...)/new static(...)/new ClassName(...)at the same parameter position, the property is effectively circular — it's only written from constructor and read to write to another instance's constructor. The fix uses the scope's function call stack to identify these self-write reads and exclude them from the "has been read" determination.Test
The regression test covers:
new self()(reported)new self($this->b, $this->a)(NOT reported - different parameter)new static()(reported)new ClassName()with explicit class name (reported)new self(b: $this->b, a: $this->a)(reported)new self(b: $this->a, a: $this->b)(NOT reported)Analogous cases probed and found not applicable:
Fixes phpstan/phpstan#14573