Fix phpstan/phpstan#14352: "Cannot re-assign $this." false-positive#5281
Fix phpstan/phpstan#14352: "Cannot re-assign $this." false-positive#5281staabm merged 11 commits intophpstan:2.1.xfrom
Conversation
ad07aca to
38aade2
Compare
38aade2 to
4f11780
Compare
VincentLanglet
left a comment
There was a problem hiding this comment.
$this = $value should still be reported
yes. thats tested via |
I mean $this = $value when $this is an ArrayAccess |
|
I see. added another test showing it still errors |
…his reassignment $this = $value should still be reported even when $value implements ArrayAccess. The fix now tracks whether the VariableAssignNode originated from a dimension-fetch assignment ($this[$key] = $value) vs a direct assignment ($this = $value). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Pushed successfully. Here's a summary of the changes: Problem: The original fix checked if the assigned expression's type implements Solution: Added a
|
…e for $this reassignment" This reverts commit 8d2b7d4.
| class TestPlain | ||
| { | ||
| public function doFoo(string $key, string $value): void | ||
| { | ||
| $this[$key] = $value; | ||
| } | ||
| } |
There was a problem hiding this comment.
I know the case
class TestPlain
{
public function doFoo(string $key, string $value): void
{
$this[$key] = $value;
}
}
might sometimes works if we extends this class and implement ArrayAccess.
But on the opposide, the code
$t = new TestPlain();
$t->doFoo('', '');
will crash.
IMHO ->yes() should be !->no()
and we will have a behavior similar to https://phpstan.org/r/ae445bd2-da35-4b9f-b0cb-a44c0d1b71e8
There was a problem hiding this comment.
Pushed. Here's a summary of the changes:
Problem: The reviewer pointed out that for non-final classes like TestPlain, $this[$key] = $value should not error because a subclass might implement ArrayAccess. The check should use !->no() instead of ->yes().
Changes:
-
VariableAssignNode— AddeddimFetchflag to distinguish$this[$key] = $value(dim-fetch) from$this = $value(direct assignment) -
AssignHandler— PassdimFetch: truewhen creatingVariableAssignNodefrom dim-fetch assignment paths -
InvalidVariableAssignRule— Changed the check to:- Use
$node->isDimFetch()to only suppress errors for dim-fetch assignments - Check
$scope->getType($variable)(the type of$this) instead of the assigned expression type - Use
!->no()instead of->yes()— this allows the "maybe" case for non-final classes (line 614 ofObjectType::isSuperTypeOfreturnsMaybewhen checking an interface against a non-final class)
- Use
-
Test data — Added
TestArrayAccessReassigncase to verify$this = $otherstill errors even when$otherimplementsArrayAccess
Behavior:
TestArrayAccess(implements ArrayAccess):$this[$key] = $value→ no error,$this = $value→ errorTestArrayAccessReassign:$this = $other→ error (even though$otheris ArrayAccess)FinalTestPlain(final, no ArrayAccess):$this[$key] = $value→ errorTestPlain(non-final, no ArrayAccess):$this[$key] = $value→ no error (subclass might implement ArrayAccess)
…eassignment Instead of checking the assigned expression type, use a dimFetch flag on VariableAssignNode to distinguish $this[$key] = $value from $this = $value. Check $this type with !->no() so non-final classes that might implement ArrayAccess through subclasses are not falsely reported. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…Access reassignment" This reverts commit 5c5e3c7.
closes phpstan/phpstan#14352
fixes the CI build