Skip to content

Resolve $this on both sides of a final class's method signature check - #6641

Open
SanderMuller wants to merge 1 commit into
phpstan:2.3.xfrom
SanderMuller:fix-final-this-signature
Open

SanderMuller wants to merge 1 commit into
phpstan:2.3.xfrom
SanderMuller:fix-final-this-signature

Conversation

@SanderMuller

Copy link
Copy Markdown
Contributor

Closes phpstan/phpstan#13418

In a final class, MethodSignatureRule reported a method as incompatible with a parent type that prints the same:

Return type (Bug13418Implements\Rel<$this(Bug13418Implements\Direct)>) of method Bug13418Implements\Direct::rel() should be compatible with return type (Bug13418Implements\Rel<$this(Bug13418Implements\Direct)>) of method Bug13418Implements\Billable<$this(Bug13418Implements\Direct)>::rel()

transformStaticType() changes static and $this in the parent's type to the plain class when the declaring class is final. The child's own $this stayed a ThisType. Inside an invariant template argument, the class and $this(Direct) then do not match. static in the child does not have the problem, because PHPStan already resolves it to the class in a final class. Non-final classes are not affected, because there transformStaticType() keeps the $this.

This PR applies transformStaticType() to the child's type too, at the two comparison points. The types in the error messages do not change.

The test data has the issue's snippet. It also has the @implements Billable<$this> shape, through a trait and as a direct method, for return and parameter types. WrongClass (Rel<Other>) is still reported.

In a final class, a child Rel<$this> against a parent Rel<NamedParent> is now accepted. It was reported before. The parent side already worked this way: a parent Rel<$this> against a child Rel<ConcreteClass> was already accepted. NamedParent and ConcreteClass in the test data cover both directions.

make tests, make phpstan and phpcs on the changed files pass. The new test fails without the change. I did not measure performance. The change adds one type traversal for each compared return or parameter type.

🤖 Generated with Claude Code

MethodSignatureRule changed the parent's $this to the plain class in a
final class, but kept the child's $this. Inside an invariant template
argument the two types then did not match, and the rule reported an
override as incompatible with a type that prints the same.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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.

PHPStan incorrectly reports method.childReturnType error for generic template inheritance with $this types

1 participant