Skip to content

Fix InstalledPackageResolver cwd fallback lost by promoted property - #8237

Merged
TomasVotruba merged 1 commit into
mainfrom
fix-installed-package-resolver-cwd-fallback
Jul 31, 2026
Merged

Fix InstalledPackageResolver cwd fallback lost by promoted property#8237
TomasVotruba merged 1 commit into
mainfrom
fix-installed-package-resolver-cwd-fallback

Conversation

@TomasVotruba

Copy link
Copy Markdown
Member

InstalledPackageResolver reassigns the local $projectDirectory variable in the constructor, but the value is bound to a promoted readonly property. The reassignment never reaches $this->projectDirectory, which stays null:

public function __construct(
    private readonly ?string $projectDirectory = null
) {
    // fallback to root project directory
    if ($projectDirectory === null) {
        $projectDirectory = getcwd(); // <-- only the local variable
    }

    Assert::directory($projectDirectory);
}

resolveVendorDir() then builds null . '/vendor' = /vendor, so resolve() always throws:

The installed package json not found. Make sure you run composer update and the "vendor/composer/installed.json" file exists

This is invisible for SetManager, because RectorConfigBuilder passes getcwd() explicitly. It is hit by the autowired instance behind the freshly added ComposerPackageConstraintFilter — any rule implementing ComposerPackageConstraintInterface (#7877) currently crashes.

-    public function __construct(
-        private readonly ?string $projectDirectory = null
-    ) {
-        // fallback to root project directory
-        if ($projectDirectory === null) {
-            $projectDirectory = getcwd();
-        }
-
-        Assert::directory($projectDirectory);
-    }
+    private readonly string $projectDirectory;
+
+    public function __construct(?string $projectDirectory = null)
+    {
+        // fallback to root project directory
+        $this->projectDirectory = $projectDirectory ?? (string) getcwd();
+
+        Assert::directory($this->projectDirectory);
+    }

Covered by a new test case that constructs the resolver without arguments.

…erty

The constructor reassigned the local $projectDirectory variable, but the promoted readonly property kept the original null. Any instance created without an explicit directory - e.g. the autowired one used by ComposerPackageConstraintFilter - then resolved the vendor dir as '/vendor' and always threw.
@TomasVotruba
TomasVotruba merged commit 29d0a00 into main Jul 31, 2026
65 checks passed
@TomasVotruba
TomasVotruba deleted the fix-installed-package-resolver-cwd-fallback branch July 31, 2026 10:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant