Report impure method overriding pure parent method in MethodSignatureRule#5584
Report impure method overriding pure parent method in MethodSignatureRule#5584phpstan-bot wants to merge 10 commits intophpstan:2.1.xfrom
MethodSignatureRule#5584Conversation
VincentLanglet
left a comment
There was a problem hiding this comment.
Add test for static method too.
|
Done. Added static method test cases covering:
All tests pass and |
VincentLanglet
left a comment
There was a problem hiding this comment.
Why tests are failing on PHP 7.4 ?
|
The PHP 7.4 test failure is fixed. The issue was that The fix makes the trait abstract method error expectation conditional on |
53f49ca to
ea28b6b
Compare
| $method->getName(), | ||
| $parentMethodDeclaringClass->getDisplayName(), | ||
| $parentMethod->getName(), | ||
| ))->identifier('method.purity')->build(); |
There was a problem hiding this comment.
Identifier must be method.impure.
Also this new error should be behind a dedicated toggle which is enabled behind bleedingedge
There was a problem hiding this comment.
Both review comments addressed and pushed:
- Identifier changed:
method.purity→method.impure - Toggle added: New
checkMethodPurityOverridefeature toggle (defaults tofalse, enabled inbleedingEdge.neon). The check inMethodSignatureRuleis now gated behind$this->checkPurity, which is wired to%featureToggles.checkMethodPurityOverride%inservices.neon.
All 11,987 tests pass and make phpstan reports no errors.
| reportNestedTooWideType: bool() | ||
| assignToByRefForeachExpr: bool() | ||
| curlSetOptArrayTypes: bool() | ||
| checkMethodPurityOverride: bool() |
There was a problem hiding this comment.
Change for reportMethodPurityOverride
There was a problem hiding this comment.
Renamed checkMethodPurityOverride to reportMethodPurityOverride across all four config files (bleedingEdge.neon, config.neon, parametersSchema.neon, services.neon). All 11,987 tests pass and make phpstan reports no errors.
| reportMaybes: %reportMaybesInMethodSignatures% | ||
| reportStatic: %reportStaticMethodSignatures% | ||
| checkPurity: %featureToggles.checkMethodPurityOverride% | ||
| checkPurity: %featureToggles.reportMethodPurityOverride% |
There was a problem hiding this comment.
This should be also reportMethodPurityOverride
There was a problem hiding this comment.
Renamed the checkPurity constructor parameter and service argument to reportMethodPurityOverride for consistency with the config toggle name. All tests pass (43/43) and make phpstan reports no errors.
…eRule` - Add purity compatibility check in MethodSignatureRule::processNode() - When a parent method has @phpstan-pure and the child method has @phpstan-impure, report an error with identifier method.impureOverridePure - The check runs for all parent sources: parent classes, interfaces, and abstract trait methods - Covers @phpstan-all-methods-pure on parent class (purity is inherited per-method) - Also covers grandchild inheritance and multiple interface implementation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Trait abstract method detection in collectParentMethods does not work
on PHP 7.4, consistent with other trait-related tests in this file
that use #[RequiresPhp('>= 8.0.0')].
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…bled in bleedingEdge Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tency Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
84fb578 to
e0144c9
Compare
| class ChildImpureOverridesPure extends Foo | ||
| { | ||
|
|
||
| /** @phpstan-impure */ |
There was a problem hiding this comment.
we should also test the case of a method returning :void (implicit impure) beeing overridden by a pure/impure method
There was a problem hiding this comment.
Done. Added test cases for :void return type methods covering:
- Error case: Child with
@phpstan-impureoverriding a@phpstan-purevoid parent method (ChildImpureOverridesPureVoid) - No-error cases:
- Child with
@phpstan-pureoverriding a pure void parent - Child with no annotation overriding a pure void parent
- Child with
@phpstan-impureoverriding an unannotated void parent - Child with
@phpstan-pureoverriding an unannotated void parent
- Child with
All 11,993 tests pass and make phpstan reports no errors.
Test that methods returning :void (implicitly impure) are handled correctly when overriding pure/impure parent methods and when being overridden by pure/impure child methods. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
When a parent method is marked
@phpstan-pure, child classes could override it with@phpstan-impurewithout any error being reported. This violated the Liskov Substitution Principle: callers expecting a pure method would get an impure one. This PR adds a purity compatibility check toMethodSignatureRule.Changes
src/Rules/Methods/MethodSignatureRule.php: Added a check at the beginning of the parent method loop — when the child method'sisPure()isnoand the parent method'sisPure()isyes, report an error with identifiermethod.impureOverridePuretests/PHPStan/Rules/Methods/data/bug-14563.php: New test data file covering all parent method sources and edge casestests/PHPStan/Rules/Methods/MethodSignatureRuleTest.php: AddedtestBug14563()test methodRoot cause
MethodSignatureRulechecked return type covariance and parameter type contravariance for overriding methods, but had no check for purity compatibility. An impure child method could silently override a pure parent method, breaking the purity contract that callers rely on.Test
The regression test covers these cases (all producing errors):
@phpstan-impure, parent has@phpstan-pure@phpstan-impurewhile interface declares it@phpstan-pure@phpstan-all-methods-pureon parent class: child class marks method@phpstan-impure@phpstan-pureabstract method, using class marks it@phpstan-impure@phpstan-impurea method pure in the parent chain@phpstan-pure, implementing class marks it@phpstan-impure— error reported for each interfaceAnd these non-error cases (verifying no false positives):
@phpstan-pureoverriding pure parent@phpstan-pureoverriding impure parent (safe — more restrictive)@phpstan-impureoverriding unannotated parent@phpstan-all-methods-impureclass overriding pure parent (PHPDoc inheritance of@phpstan-puretakes precedence over class-level annotation)Fixes phpstan/phpstan#14563