Skip to content

Language: class constant new expression — compile rejects valid PHP 8.3+ (Zend/zend_compile.c) #10198

Description

@PurHur

Category

language · php-src-strict

Problem

PHP 8.3+ allows new expressions in class constant initializers (e.g. public const X = new C(1);). This compiler rejects them at compile time with New expressions are not supported in this context, blocking PHP 8.3/8.4 parity and self-host code using immutable constant object graphs.

Mentioned in parity snapshot #9978 but lacks a dedicated claimable issue.

php-src reference

Repro (verified 2026-06-20)

test/repro/maintainer_gap_new_in_constant.php:

<?php
class C {
    public function __construct(public int $n = 0) {}
}
class Holder {
    public const X = new C(1);
}
var_dump(Holder::X->n);
./script/docker-exec.sh -- bash -lc 'source script/php-env.sh
php bin/vm.php test/repro/maintainer_gap_new_in_constant.php 2>&1 | head -3
'
Runtime Result
Zend PHP 8.3+ int(1)
php bin/vm.php parseAndCompile failure: New expressions are not supported in this context ❌

Scope (PHP-in-PHP first)

Area Files
Parser/CFG lib/Parser.php, constant-expression allowlist
Compiler lib/Compiler.php — lower new in zend_compile_const_expr path
VM constant materialization for object constants
JIT lib/JIT/ClassConstFetchHelper.php if object constants need runtime box

Done when

  • Repro compiles and prints int(1) on VM (php-src-strict)
  • Holder::X is the same object identity across reads (Zend constant object semantics)
  • Negative: new in non-constant contexts unchanged
  • test/compliance/cases/language/class_const_new_expression.phpt guards regression
  • JIT/AOT agree with VM when both in scope

Links

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 20, 2026
  2. PurHur commented on Jun 20, 2026

    @PurHur
    OwnerAuthor

    claim: worker-lane-B — starting this run

  3. PurHur commented on Jun 20, 2026

    @PurHur
    OwnerAuthor

    Merged via #10206.

    Fix: Removed stale compile-time rejection of new in class constant initializers (NewWithoutParensCompileCheck); enabled CompilerVersion::supportsClassConstObjectExpressions() for PHP 8.3+ target. Existing VM/JIT materialization (finalizePendingNewClassConst, ClassConstMaterializer) handles object constants with shared identity.

    Verification:

    ./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && php bin/vm.php test/repro/maintainer_gap_new_in_constant.php'
    # int(1)
    
    ./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && ./vendor/bin/phpunit test/compliance/VMTest.php --filter "class_const_new|class_const_object|const_expr_new|new_in_constant"'
    # OK (9 tests)
    
    ./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && ./vendor/bin/phpunit test/compliance/JITTest.php --filter "class_const_object"'
    # OK (2 tests)
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

    IMPORTANTCritical patharea: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