Skip to content

PHP: Unknown property hooks are accepted inside discarded declarations #24795

Closed as not planned

Description

@alwyn1024

Description

Summary

PHP 8.5 and PHP 8.6 accept unknown property-hook names when the enclosing declaration is discarded during compilation, even though the same declaration is rejected when retained or compiled normally.

This creates a discrepancy in compile-time validation depending on whether the enclosing expression or declaration survives constant folding.

Minimal reproducer

<?php
false && static function() {
    return new class {
        public int $x {
            unknown => 1;
        }
    };
};

Actual behavior:

  • PHP 8.5.10: Compilation succeeds.
  • PHP 8.6.0RC4: Compilation succeeds.

Retained declaration control

<?php
$f = static function() {
    return new class {
        public int $x {
            unknown => 1;
        }
    };
};

Both PHP 8.5.10 and PHP 8.6.0RC4 reject this during compilation.

The reported diagnostic is:

Fatal error: Unknown hook "unknown" for property class@anonymous::$x, expected "get" or "set"

Ordinary class declaration control

<?php
class C {
    public int $x {
        unknown => 1;
    }
}

Both versions reject this with:

Fatal error: Unknown hook "unknown" for property C::$x, expected "get" or "set"

Valid property-hook control

<?php
class C {
    public int $x {
        get => 1;
    }
}

Both versions compile successfully.

Additional discarded-expression example

The following also compiles successfully in both PHP 8.5.10 and PHP 8.6.0RC4:

<?php
const F = true ? 1 : static function() {
    return new class {
        public int $x {
            unknown => 1;
        }
    };
};

Expected behavior / clarification requested

Should PHP reject an unknown property-hook name regardless of whether its enclosing declaration survives compilation?

Specifically, should the discarded closure and conditional-expression examples above fail compilation, or is their acceptance intentional?

If acceptance is intentional, what defines the boundary between declarations that must undergo property-hook validation and declarations eliminated during compilation?

The question concerns compile-time source validity, not runtime evaluation of unreachable branches.

Affected versions

  • PHP 8.5.10 — Windows x64
  • PHP 8.6.0RC4 — Windows x64, NTS, VC2022
  • PHP 8.6 source commit: f23b4c222cebe33be93ee8ecaaa14390c5507a08

The PHP 8.6 executable was built from the specified source commit.

Reproduce by saving each example separately and running:

php -n -l example.php

Relevant implementation

The parser permits hook names represented by T_STRING, while compiler validation recognizes get and set.

The observed acceptance appears to depend on whether compilation visits the enclosing declaration.

I would appreciate clarification on whether this is intended behaviour or a missing validation step for discarded declarations.

PHP Version

PHP 8.6.0RC4 (cli) (built: Oct 25 2026 12:45:36) (NTS Visual C++ 2022 x64)
Copyright © The PHP Group and Contributors
Zend Engine v4.6.0RC4, Copyright © Zend by Perforce
    with Zend OPcache v8.6.0RC4, Copyright ©, by Zend by Perforce

Operating System

Windows x64 (64-bit), MSVC 2022 build

Activity

  1. iluuu1994 commented on Oct 27, 2026

    @iluuu1994
    Member

    Hi @alwyn1024. You'll likely find the same for many other compile errors. I don't think this is worth fixing.

  2. alwyn1024 commented on Oct 27, 2026

    @alwyn1024
    Author

    Thank you @iluuu1994, I appreciate the response.

    I am working on an EBNF grammar specification for PHP 8.6 and just wanted to get some input regarding this from the community.

  3. iluuu1994 commented on Oct 27, 2026

    @iluuu1994
    Member

    No worries. Here's a demonstration that this affects all compile errors: https://3v4l.org/bpPsX We skip compilation of the rhs when it is known to be dead at compile time. A fix would be non-trivial, requiring compilation of the AST while discarding the generated opcodes. I don't think that's worth the complexity.

    But if you disagree, feel free to start a discussion in internals. 🙂

    Thanks for the report.

  4. alwyn1024 commented on Oct 28, 2026

    @alwyn1024
    Author

    I fully agree with your assessment @iluuu1994. Once again, thank you for the feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions