Skip to content

feat(phpstan): add MissingClosureReturnTypehintRule - #94

Merged
spawnia merged 11 commits into
masterfrom
missing-closure-return-typehint-rule
Aug 18, 2026
Merged

feat(phpstan): add MissingClosureReturnTypehintRule#94
spawnia merged 11 commits into
masterfrom
missing-closure-return-typehint-rule

Conversation

@spawnia

@spawnia spawnia commented Aug 14, 2026

Copy link
Copy Markdown
Member

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 ClosureTypehintRule base. It declares Node\FunctionLike as its node type rather than Node\Expr, which is semantically what these rules care about; the two measure the same on this repo, so the choice is readability, not speed. The instanceof filter 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.

MissingClosureParameterTypehintRule picks up two fixes along the way, both now covered by fixture cases:

  • Arrow functions were reported as "Closure". They are now labelled "Arrow function", matching the new rule. Consumers who have this rule enabled and a baseline will need to regenerate it.
  • Errors on a multi-line signature all landed on the closure's first line instead of the offending parameter's line.

Rector and php-cs-fixer skip tests/PHPStan/data — they kept adding the return types the fixtures must lack, and use_arrow_functions collapsed the multi-line closures that distinguish the two node types under test.

make rector fails on this branch with Undefined constant Rector\PHPUnit\Set\PHPUnitSetList::PHPUNIT_40. That is pre-existing on master and unrelated to this change.

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
@github-code-quality

github-code-quality Bot commented Aug 14, 2026

Copy link
Copy Markdown

Code Coverage Overview

Languages: PHP

PHP / code-coverage/phpunit

The overall coverage in commit cb096dc in the missing-closure-retu... branch is 90%. The coverage in commit 2949ba3 in the master branch is 89%.

Show a code coverage summary of the most impacted files.
File master 2949ba3 missing-closure-retu... cb096dc +/-
PHPStan/Rules/M...ypehintRule.php 0% 88% +88%
PHPStan/Rules/M...ypehintRule.php 0% 100% +100%
PHPStan/Rules/C...ypehintRule.php 0% 100% +100%

Updated August 14, 2026 10:51 UTC

Comment thread .php-cs-fixer.php Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

spawnia added 10 commits August 14, 2026 11:32
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.
@spawnia
spawnia requested a balanced review from Copilot August 14, 2026 10:50
@spawnia
spawnia marked this pull request as ready for review August 14, 2026 10:50
@spawnia
spawnia requested a review from simbig August 14, 2026 10:52

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.

Comment thread src/PHPStan/Rules/MissingClosureReturnTypehintRule.php
@spawnia
spawnia requested a review from simbig August 14, 2026 11:10
@spawnia
spawnia merged commit cb69248 into master Aug 18, 2026
30 checks passed
@spawnia
spawnia deleted the missing-closure-return-typehint-rule branch August 18, 2026 06:24
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))
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 6.14.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Development

Successfully merging this pull request may close these issues.

3 participants