Repository navigation
PHP: Unknown property hooks are accepted inside discarded declarations #24795
Description
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.phpRelevant implementation
- [Property-hook parser productions]()
php-src/Zend/zend_language_parser.y
Line 1160 in f23b4c2
property_hook: - [zend_get_property_hook_kind_from_name]()
Line 9348 in f23b4c2
zend_property_hook_kind zend_get_property_hook_kind_from_name(const zend_string *name) { - [Property-hook compilation]()
Line 9409 in f23b4c2
zend_property_hook_kind hook_kind = zend_get_property_hook_kind_from_name(name);
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
iluuu1994 commentedon Oct 27, 2026
Hi @alwyn1024. You'll likely find the same for many other compile errors. I don't think this is worth fixing.
alwyn1024 commentedon Oct 27, 2026
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.
iluuu1994 commentedon Oct 27, 2026
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.
alwyn1024 commentedon Oct 28, 2026
I fully agree with your assessment @iluuu1994. Once again, thank you for the feedback.