Skip to content

Remove the 'phpstan/phpstan' pin once Rector and drupal-rector support PHPStan 2.3.4 #3244

Open

Description

@AlexSkrypnyk

Summary

The template's root composer.json pins phpstan/phpstan to <=2.3.3 as a stopgap. With PHPStan 2.3.4, Rector crashes on every file, so ahoy lint fails on any fresh install. The pin needs to come off once the upstream fixes land, otherwise consumer sites stay stuck on an old PHPStan.

Details

Why Rector breaks

PHPStan 2.3.4 (released 2026-10-28) moved to phpstan/phpdoc-parser 2.4.0, which adds FullyQualifiedNameNode and lets CallableTypeNode accept it. ClosureType::toPhpDocNode() inside the PHPStan phar now builds a CallableTypeNode with one.

Rector ships its own unprefixed copy of phpdoc-parser (2.3.x) in vendor/rector/rector/vendor, and that copy gets autoloaded first. PHPStan's code then calls the old constructor:

[ERROR] Could not process "web/modules/custom/ys_base/tests/src/Kernel/ExampleTest.php" file, due to:
"System error: "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"

PHPStan's own analysis still passes. Only Rector, which runs PHPStan in-process, fails. Every released Rector version is affected, including the latest, 2.8.2.

Why upgrading Rector isn't enough

Vortex can't move past Rector 2.6.1 anyway: palantirnet/drupal-rector 1.1.3 declares conflict: rector/rector >=2.6.2, because Rector 2.6.2 removed PHPUnitSetList, which drupal-rector's set lists depend on.

Upstream blockers

Both have to land and be released before the pin can go:

Done when

  • A palantirnet/drupal-rector release allows a Rector version whose bundled phpdoc-parser is 2.4 or newer.
  • phpstan/phpstan in the root composer.json goes back to a caret constraint (^2.3.4 or higher).
  • ahoy lint passes with Rector on a fresh install.

Note on the constraint form

The pin is <=2.3.3 rather than ^2.3.1 <2.3.4 because the installer's snapshot normaliser only collapses single-token constraints to __VERSION__. A 2-part range would change every installer fixture. A plain caret constraint is fine when the pin is removed, so no snapshot refresh is needed.

Activity

  1. added this to the 1.43.0 milestone on Oct 28, 2026
  2. added
    BLOCKEDIssue or pull request is blocked
    UPSTREAMIssue or pull request is related to an upstream project
    on Oct 28, 2026
  3. AlexSkrypnyk commented on Oct 29, 2026

    @AlexSkrypnyk
    MemberAuthor

    Status as of 2026-10-30: half unblocked.

    Verified locally: with the pin removed, Composer resolves PHPStan 2.3.4 but leaves Rector on 2.6.1. A cache-cleared rector --dry-run then fails on every file with the same CallableTypeNode::__construct() error. With the pin in place, the same cache-cleared run passes on all 64 files.

    Watch out when checking this: a plain ahoy lint-be can pass with the pin removed, because Rector's result cache skips files that passed under 2.3.3. CI has no cache, so test with --clear-cache.

    Next step: once a drupal-rector release allows Rector 2.8.3 or later, set phpstan/phpstan back to ^2.3.4 and run a cache-cleared Rector to confirm.

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

    BLOCKEDIssue or pull request is blockedUPSTREAMIssue or pull request is related to an upstream project

    Type

    No type

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions