Skip to content

Language: supportsInterfaceTypedConstants() ignores 8.2 profile withholding (re-#24809, lib/CompilerVersion.php) #24917

Closed

Description

@PurHur

What

The two predicates that gate typed class constants disagree, and the difference is not deliberate as far as I can tell.

lib/CompilerVersion.php:

public static function supportsInterfaceTypedConstants(): bool
{
    return version_compare(self::VERSION, '8.3', '>=');   // plain version check -> TRUE
}

versus supportsTypedClassConstants(), whose own docblock says:

Withheld on 8.4.0-dev reference profile (phpversion() 8.2.31 matches Zend 8.2 parse error).
Enable via stable 8.4.0+ or explicit PHP_COMPILER_PROFILE=8.3 / 8.4 forward profile.
Do not use VERSION_ID / isForwardProfileAtLeast here — that re-enabled acceptance on default after #24719 and broke Zend 8.2 parity (#24809, re-#22782/#22705).

Measured at 90c654c46:

supportsInterfaceTypedConstants() => true
supportsTypedClassConstants()     => false

But an interface typed constant is a typed class constant. public const array X = [1] inside an interface is rejected by Zend 8.2 exactly like the class form — verified against the host interpreter (PHP 8.2.32) and against the compiler, which produce the identical error:

syntax error, unexpected identifier "X", expecting "="

So the compiler is correct here. The predicate is what is wrong.

Effect

Four cases guard on the stale predicate. With --SKIPIF-- now honoured (#24888), two of them run when they should be skipped and fail:

case expects result
language/interface_typed_const rejection ✔ passes
language/interface_typed_const_inherit_fail rejection ✔ passes
language/interface_typed_const_inherit_ok 8.3+ feature to work ✘ fails
language/interface_typed_const_inherit_error 8.3+ feature to work ✘ fails

Both failures are in the committed VMTest.failing baseline, so they currently read as compiler debt when they are neither compiler bugs nor real coverage.

The two that pass do so because they assert the rejection, which is the behaviour the reference profile actually has — consistent with the withholding being intentional for the class form.

Suggested fix

Have supportsInterfaceTypedConstants() apply the same withholding as supportsTypedClassConstants() — or express it in terms of it — so the two cannot drift again. The docblock on the latter already warns against exactly the version_compare-style shortcut the former still uses.

Found while verifying #24888; these two were the residue left after SKIPIF started working.

Activity

  1. added
    bugSomething isn't working
    implementation-readySpec complete: repro, php-src ref, done-when — safe for workers to claim
    on Jul 29, 2026
  2. changed the title [-]supportsInterfaceTypedConstants() ignores the 8.2 reference-profile withholding that supportsTypedClassConstants() applies[/-] [+]Language: supportsInterfaceTypedConstants() ignores 8.2 profile withholding (re-#24809, lib/CompilerVersion.php)[/+] on Jul 29, 2026
  3. PurHur commented on Jul 29, 2026

    @PurHur
    OwnerAuthor

    claim: worker-lane-C — starting this run

    Trust snapshot (pre-claim):

    • docker info: ok
    • bootstrap-inventory --check: red (construct-flag drift in lib/Compiler.php + ThrowInClassConstCompileCheck.php; file-list regen needed) — pre-existing on tree, not blocking this language predicate fix
    • release-readiness --json: still running; will note result on PR if relevant
  4. PurHur commented on Jul 29, 2026

    @PurHur
    OwnerAuthor

    Merged #24938 (b42dc21d68).

    Fix: supportsInterfaceTypedConstants() now delegates to supportsTypedClassConstants() — same 8.2 reference-profile withholding as the class form.

    Verification:

    • Unit filter (gate + reject + inherit under PROFILE=8.3): OK 8/8
    • Default profile VM interface_typed_const*: 4 skipped (SKIPIF)
    • PHP_COMPILER_PROFILE=8.3 VM same filter: OK 4/4
    • Repro: unset → syntax error, unexpected identifier "X", expecting "="; 8.3 → a

    Baselines: removed the two false .failing entries and all four from .executed (skipped ≠ executed).

  5. PurHur commented on Jul 29, 2026

    @PurHur
    OwnerAuthor

    Verified fixed — with one coverage note

    Re-checked empirically at b42dc21d6 rather than from the commit message:

    supportsInterfaceTypedConstants = false
    supportsTypedClassConstants     = false
    

    The two predicates now agree, which was the defect.

    All four cases now skip:

    ↩ language/interface_typed_const
    ↩ language/interface_typed_const_inherit_error
    ↩ language/interface_typed_const_inherit_fail
    ↩ language/interface_typed_const_inherit_ok
    Tests: 4, Assertions: 0, Skipped: 4
    

    The note: before this change, interface_typed_const and interface_typed_const_inherit_fail passed — they assert that the 8.2 reference profile rejects interface typed constants, which is the behaviour the profile actually has. They now skip, so nothing verifies that rejection any more.

    Zero assertions ran for this feature on the default profile. That is a small coverage loss rather than a bug, and it may well be intentional if these cases are considered 8.3+-only. Flagging it because it is exactly the FIXED-vs-SKIPPED distinction the compliance gate now reports separately (#24933): two cases stopped failing here, but two others stopped asserting, and only the first kind is progress.

    If the rejection behaviour is worth pinning, the two reject-shaped cases want a guard that keeps them running on the reference profile — the same split typed_class_const_reject / typed_class_const_reference_profile already get in VMTest.php.

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 / JITbugSomething isn't workingimplementation-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