Skip to content

Fix phpstan/phpstan#12246: crash on first class callable as conditional do while#5194

Merged
staabm merged 5 commits intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-isjxsf9
Mar 11, 2026
Merged

Fix phpstan/phpstan#12246: crash on first class callable as conditional do while#5194
staabm merged 5 commits intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-isjxsf9

Conversation

@phpstan-bot
Copy link
Collaborator

Summary

Using a first-class callable (e.g. $this->textElement(...)) as a do...while loop condition caused a crash: Call to undefined method PHPStan\Node\Printer\Printer::pPHPStan_Node_MethodCallableNode(). This fix adds the missing printer methods for all callable node types.

Changes

  • Added pPHPStan_Node_MethodCallableNode() to src/Node/Printer/Printer.php
  • Added pPHPStan_Node_FunctionCallableNode() to src/Node/Printer/Printer.php
  • Added pPHPStan_Node_StaticMethodCallableNode() to src/Node/Printer/Printer.php
  • Added pPHPStan_Node_InstantiationCallableNode() to src/Node/Printer/Printer.php
  • Each method delegates to printing the original PHP-Parser AST node via getOriginalNode()
  • Added regression test in tests/PHPStan/Analyser/data/bug-12246.php
  • Added test method testBug12246 in tests/PHPStan/Analyser/AnalyserIntegrationTest.php

Root cause

When a first-class callable is used as a do...while condition, NodeScopeResolver converts the MethodCall to a MethodCallableNode and processes it. At the end of processExprNode, the truthy/falsey scope callbacks call $scope->filterByTruthyValue($expr) with the MethodCallableNode. This calls getNodeKey() which uses ExprPrinter::printExpr(), which delegates to the Printer class. The Printer (extending PhpParser\PrettyPrinter\Standard) looks for a method named pPHPStan_Node_MethodCallableNode() based on the node's getType() return value, but no such method existed.

The fix adds printer methods for all four callable node types (FunctionCallableNode, MethodCallableNode, StaticMethodCallableNode, InstantiationCallableNode), each delegating to printing the original call expression node.

Test

The regression test uses a do...while loop with $this->textElement(...) as the condition. Without the fix, this crashes with the printer error. With the fix, PHPStan correctly reports that the do-while condition is always true (since a Closure is always truthy).

Fixes phpstan/phpstan#12246

- Added printer methods for MethodCallableNode, FunctionCallableNode,
  StaticMethodCallableNode, and InstantiationCallableNode to Printer
- These nodes delegate to printing their original AST node
- The crash occurred because filterByTruthyValue/filterByFalseyValue
  tried to print callable nodes that had no printer method
- New regression test in tests/PHPStan/Analyser/data/bug-12246.php

Closes phpstan/phpstan#12246
@staabm staabm requested a review from VincentLanglet March 11, 2026 07:05
@staabm
Copy link
Contributor

staabm commented Mar 11, 2026

I verified that all added methods are covered by a test which crashes without the methods beeing present

Copy link
Contributor

@VincentLanglet VincentLanglet left a comment

Choose a reason for hiding this comment

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

I dunno this class but all other methods use sprintf for the implementation, why not the new methods ?

@clxmstaab clxmstaab force-pushed the create-pull-request/patch-isjxsf9 branch from 1e706aa to 945bccf Compare March 11, 2026 09:00
@staabm staabm merged commit bb4650d into phpstan:2.1.x Mar 11, 2026
631 of 650 checks passed
@staabm staabm deleted the create-pull-request/patch-isjxsf9 branch March 11, 2026 09:16
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.

3 participants