Skip to content

Fix #6777: Bogus write-only error when appending to an array-like object in private class property#5102

Open
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-ryr3pbw
Open

Fix #6777: Bogus write-only error when appending to an array-like object in private class property#5102
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-ryr3pbw

Conversation

@phpstan-bot
Copy link
Collaborator

Summary

When appending to an ArrayAccess object stored in a private class property (e.g. $this->array[] = $s), PHPStan incorrectly reported "Property is never read, only written." This is a false positive because appending to an ArrayAccess object is semantically $this->array->offsetSet(null, $s) — a method call that reads the property.

Changes

  • Modified src/Node/ClassStatementsGatherer.php: When handling a PropertyAssignNode, check if the assigned expression is a SetOffsetValueTypeExpr or SetExistingOffsetValueTypeExpr (indicating array dim fetch assignment) and the property type is an ArrayAccess object. If so, also record a PropertyRead.
  • Updated existing WriteToCollection test expectations in tests/PHPStan/Rules/DeadCode/UnusedPrivatePropertyRuleTest.php to reflect the fix.
  • Added regression test in tests/PHPStan/Rules/DeadCode/data/bug-6777.php.

Root cause

In ClassStatementsGatherer, when NodeScopeResolver processes $this->array[] = $s on an ArrayAccess property, it emits a PropertyAssignNode which was unconditionally recorded as a PropertyWrite. Meanwhile, the PropertyFetch for $this->array was processed in expression-assign mode, causing ClassStatementsGatherer to skip recording a PropertyRead. This resulted in the property being tracked as "only written" even though it was being read to call offsetSet() on the object.

The fix detects when a property assignment comes from an array dim fetch operation on an ArrayAccess object and also records a PropertyRead, since the object must be read from the property to invoke the method.

Test

Added tests/PHPStan/Rules/DeadCode/data/bug-6777.php which reproduces the original issue: a class with a private ArrayObject property that is only appended to via $this->array[] = $s. The test expects no errors.

Fixes phpstan/phpstan#6777

- In ClassStatementsGatherer, also record a PropertyRead when a PropertyAssignNode
  is for an ArrayAccess property via array dim fetch (e.g. $this->array[] = $s),
  because this is semantically $this->array->offsetSet() which reads the property
- New regression test in tests/PHPStan/Rules/DeadCode/data/bug-6777.php
- Updated existing WriteToCollection test expectations

Closes phpstan/phpstan#6777
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant