Skip to content

Regression: constructor-promoted asymmetric visibility public private(set) — compile fatal (re-#4690) #6981

Closed

Description

@PurHur

Category

language · php-src-strict

Problem

PHP 8.4 allows asymmetric visibility on constructor-promoted properties, e.g. public function __construct(public private(set) string $name). Non-promoted public private(set) string $name compiles and enforces correctly on VM today, but the promoted form fails at compile with:

Multiple access type modifiers are not allowed

Closed #4690 tracked this gap; the parser/rewriter still rejects valid php-src syntax, blocking PHP 8.4 parity and self-host code using promoted asymmetric properties.

php-src reference

Repro (failure today)

<?php
class User {
    public function __construct(
        public private(set) string $name,
    ) {}
}
$u = new User('alice');
echo $u->name, "\n";
try {
    $u->name = 'bob';
} catch (Error $e) {
    echo $e->getMessage(), "\n";
}
./script/docker-exec.sh -- bash -lc 'source script/php-env.sh
php bin/vm.php repro.php
'
Runtime Compile Runtime
Zend PHP 8.4+ OK alice + cannot modify private(set)
vm.php today Fatal: Multiple access type modifiers —

Control (works today): non-promoted public private(set) string $name = 'x'; in the same file compiles and throws on external write.

Also fails: public readonly private(set) on promoted parameters (same parse fatal).

Scope (this repo)

Layer Path
Parser / preprocessor lib/SourcePreprocessor/AsymmetricVisibilityRewriter.php — allow private(set) on promoted params
Compiler lib/Compiler.php — promoted param metadata → asymmetricSetVisibilityFromCfgOp
VM / JIT lib/VM.php, lib/JIT/AsymmetricVisibilityGuard.php — same guards as non-promoted
Tests test/compliance/cases/language/asymmetric_visibility_promoted_ctor.phpt

PHP-in-PHP: no new C runtime branches.

Done when

  • Repro compiles on VM, JIT, and AOT
  • External $u->name = 'bob' throws catchable Error matching Zend message
  • Writes from inside class / constructor still allowed
  • Non-promoted asymmetric properties remain green (no regression)
  • ./script/ci-fast.sh --filter asymmetric_visibility_promoted green

Verification

./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && ./vendor/bin/phpunit --filter asymmetric_visibility_promoted'

Related

Activity

  1. added
    enhancementNew feature or request
    area:vmVirtual machine
    implementation-readySpec complete: repro, php-src ref, done-when — safe for workers to claim
    on Jun 6, 2026
  2. PurHur commented on Jun 6, 2026

    @PurHur
    OwnerAuthor

    claim: worker-lane-b — starting this run

  3. PurHur commented on Jun 6, 2026

    @PurHur
    OwnerAuthor

    Merged via #6988.

    Fix: AsymmetricVisibilityCompileCheck::verifyPromotedParam() no longer treats public promotion + private(set) as duplicate modifiers — matches PHP 8.4 RFC asymmetric-visibility-v2 / zend_compile.c.

    Verification:

    ./script/docker-exec.sh -- bash -lc 'source script/php-env.sh
    php bin/vm.php test/repro/asymmetric_visibility_promoted_ctor.php
    vendor/bin/phpunit --filter asymmetric_visibility_promoted
    '

    → compiles, prints alice, external write throws Cannot modify private(set) property User::$name from global scope.

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

    area:compilerCompiler / CFG / JITarea:vmVirtual machineenhancementNew feature or requestimplementation-readySpec complete: repro, php-src ref, done-when — safe for workers to claimphase-2:languagePhase 2 – language features

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions