Skip to content

Rector 2.8.2 + PHPStan 2.3.4: CallableTypeNode::__construct() expects IdentifierTypeNode, FullyQualifiedNameNode given (bundled phpdoc-parser 2.3.11) #9947

Closed

Description

@ggiak

Bug Report

Subject Details
Rector version 2.8.2, with phpstan/phpstan 2.3.4

With PHPStan 2.3.4, Rector 2.8.2 fails on any file where PHPStan has to describe a closure type that came from a docblock. With PHPStan 2.3.3 the same file passes.

[ERROR] Could not process "src/Repro.php" file, due to:
"PHPStan\PhpDocParser\Ast\Type\CallableTypeNode::__construct(): Argument #1 ($identifier) must be of type
PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode, PHPStan\PhpDocParser\Ast\Type\FullyQualifiedNameNode given,
called in phar://vendor/phpstan/phpstan/phpstan.phar/src/Type/ClosureType.php:759"

The cause seems to be packaging, not a rule. PHPStan 2.3.4 updated its phpdoc-parser to 2.4.0, which adds FullyQualifiedNameNode and accepts it in CallableTypeNode (phpstan/phpdoc-parser#339). ClosureType::toPhpDocNode() in the phar now builds a CallableTypeNode with one. Rector 2.8.2 ships its own unprefixed phpstan/phpdoc-parser 2.3.11 in vendor/rector/rector/vendor, and that copy is the one autoloaded. So PHPStan's code ends up calling the old 2.3.11 constructor.

Stack (top):

#0 phar://.../phpstan.phar/src/Type/ClosureType.php(759): CallableTypeNode->__construct(FullyQualifiedNameNode, ...)
#1 phar://.../phpstan.phar/src/Type/ClosureType.php(301): ClosureType->toPhpDocNode()
#2 phar://.../phpstan.phar/src/Type/ClosureType.php(291): ClosureType->describeCallable()
...
#5 phar://.../phpstan.phar/src/Type/ObjectType.php(464): ClosureType->describe(VerbosityLevel)
#6 phar://.../phpstan.phar/src/Analyser/ExprHandler/FuncCallHandler.php(219): ObjectType->isSuperTypeOf(ClosureType)

Minimal PHP Code Causing Issue

The demo can't pin the PHPStan version, so here's a standalone reproduction instead:

composer.json

{"require-dev": {"rector/rector": "2.8.2", "phpstan/phpstan": "2.3.4"}}

src/Repro.php

<?php

final class Repro
{
    /**
     * @param  Closure(int):int  $next
     */
    public function run(int $value, Closure $next): int
    {
        return $next($value);
    }
}

rector.php

<?php

use Rector\Config\RectorConfig;
use Rector\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNativeCallRector;

return RectorConfig::configure()
    ->withPaths([__DIR__.'/src'])
    ->withRules([ReturnTypeFromStrictNativeCallRector::class]);

vendor/bin/rector process --dry-run → the error above. With "phpstan/phpstan": "2.3.3" → [OK] Rector is done!

Expected Behaviour

The file is processed with no error. The bundled phpdoc-parser probably needs bumping to 2.4.0, or Rector should declare conflict: phpstan/phpstan >=2.3.4 until it is, so Composer doesn't install a combination that breaks.

Activity

  1. samsonasik commented on Oct 29, 2026

    @samsonasik
    Member

    wait for:

    you can temporary uses:

    "phpstan/phpstan": "2.3.3"

    in your composer.json for now.

  2. samsonasik commented on Oct 29, 2026

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions