feat(phpstan): add MissingClosureReturnTypehintRule - #94
Merged
Conversation
Closures and arrow functions without a return type force readers and static analysis to infer behavior from the implementation. Rector's TYPE_DECLARATION set cannot infer types from magic properties, so a dedicated rule closes the gap. Disabled by default in rules.neon, like its parameter counterpart. 🤖 Generated with Claude Code
Code Coverage OverviewLanguages: PHP PHP / code-coverage/phpunitThe overall coverage in commit cb096dc in the Show a code coverage summary of the most impacted files.
Updated |
spawnia
commented
Aug 14, 2026
There was a problem hiding this comment.
Pull request overview
Adds an opt-in PHPStan rule requiring native return types on closures and arrow functions.
Changes:
- Implements and registers the new rule.
- Adds positive and negative rule tests.
- Excludes intentional PHPStan fixtures from automated rewriting.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
src/PHPStan/Rules/MissingClosureReturnTypehintRule.php |
Implements return-type validation. |
tests/PHPStan/MissingClosureReturnTypehintRuleTest.php |
Tests reported violations. |
tests/PHPStan/data/closure-return-types.php |
Provides typed and untyped fixtures. |
rules.neon |
Adds disabled-by-default registration. |
rector.php |
Excludes PHPStan fixtures from Rector. |
.php-cs-fixer.php |
Excludes PHPStan fixtures from formatting. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Both closure typehint rules shared getNodeType() and the same Closure/ArrowFunction filter.
PHPStan dispatched the rule for every expression node to reach two instanceof checks. No measurable difference on this repo (276 files), but consumers analyse far more code.
The rule shipped untested and now shares a base class with the new return typehint rule. Documents RuleTestCase as the convention.
Arrow function parameters were reported as "Closure parameter". Extracts closureKind() so both rules phrase the node kind the same way. The FunctionLike filter was load-bearing but untested - deleting it kept both suites green. Fixtures now include an untyped plain function and class method that the rules must ignore.
RuleErrorBuilder defaults to the closure start line, so every parameter of a multi-line signature was misreported.
$paramVar->name was written twice: once in the is_string() guard and once when assigned to $varName.
…bers The arrow function label and the processClosure() extraction both escaped the message patterns in phpstan/php-below-8.1.neon.
simbig
requested changes
Aug 14, 2026
simbig
approved these changes
Aug 14, 2026
github-actions Bot
pushed a commit
that referenced
this pull request
Aug 18, 2026
## [6.14.0](v6.13.3...v6.14.0) (2026-08-18) ### Features * **phpstan:** add MissingClosureReturnTypehintRule ([#94](#94)) ([cb69248](cb69248))
|
🎉 This PR is included in version 6.14.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closures and arrow functions without an explicit return type force readers and static analysis to infer behavior from the implementation. Rector's TYPE_DECLARATION set fixes methods but cannot infer closure types from magic properties (e.g. Eloquent relations), so a dedicated PHPStan rule closes that gap next to the existing
MissingClosureParameterTypehintRule.Both rules now share a
ClosureTypehintRulebase. It declaresNode\FunctionLikeas its node type rather thanNode\Expr, which is semantically what these rules care about; the two measure the same on this repo, so the choice is readability, not speed. Theinstanceoffilter in the base is load-bearing — without it both rules fire on every named function, method and PHP 8.4 property hook — so the fixtures include untyped named functions and methods to keep it honest.The new rule is disabled by default in
rules.neon, like its parameter counterpart, so consumers can enable it per project or per module. This repo enables both on itself.MissingClosureParameterTypehintRulepicks up two fixes along the way, both now covered by fixture cases:Rector and php-cs-fixer skip
tests/PHPStan/data— they kept adding the return types the fixtures must lack, anduse_arrow_functionscollapsed the multi-line closures that distinguish the two node types under test.make rectorfails on this branch withUndefined constant Rector\PHPUnit\Set\PHPUnitSetList::PHPUNIT_40. That is pre-existing onmasterand unrelated to this change.