PHP RFC: Attributes on Constants
- Version: 0.2
- Date: 2024-11-30
- Author: Daniel Scherzer, daniel.e.scherzer@gmail.com
- Status: Under Discussion
- First Published at: http://wiki.php.net/rfc/attributes-on-constants
- Implementation: https://github.com/php/php-src/pull/16952
Introduction
Attributes were first introduced in attributes_v2, with the current syntax adopted shorter_attribute_syntax_change. This RFC would add support for attributes on
- Compile-time non-class constants
To the list of current valid targets (see attribute_syntax):
- functions (including closures and short closures)
- classes (including anonymous classes), interfaces, traits
- class constants
- class properties
- class methods
- function/method parameters
Additionally, taking advantage of this new feature, the #[\Deprecated]
attribute is updated to also target compile-time non-class constants.
“Compile-time non-class constants” refers to constants defined via const MY_CONST = 5;
(for example) rather than those via define( 'MY_CONST', 5 );
. Unless clear from context, in this RFC “constant” refers to a compile-time non-class constant.
Proposal
Attributes are allowed to target constants, with the introduction of a Attribute::TARGET_CONSTANT
. Additionally, Attribute::TARGET_ALL
will now include constants.
To prevent confusing code, attributes are only allowed to be applied to constants that are declared in their own statement:
// This is okay #[\MyAttribute] const Example1 = 1; // This is an error #[\MyAttribute] const Example2 = 2, Example3 = 3;
To expose information about these attributes to runtime, ReflectionConstant::getAttributes()
is introduced.
Additionally, the #[\Deprecated]
attribute is updated to allow targeting constants; when applied, the constant is marked with CONST_DEPRECATED
.
Backward Incompatible Changes
Given that Attribute
is final
, the added constant shouldn't cause any conflicts. Likewise, ReflectionConstant
is final, so the added method shouldn't cause any conflicts.
Existing attributes that use Attribute::TARGET_ALL
may need to be updated if they do not apply to constants.
Furthermore, as with all RFCs that make code that previously had a compile-time error become valid, this RFC requires updates to static analyzers and IDEs to understand the semantics of adding attributes to constants and not erroneously report errors.
Proposed PHP Version(s)
Next version of PHP (PHP 8.5 or PHP 9.0)
RFC Impact
To SAPIs
Just noting for completion: the current implementation passes the attribute information to runtime via a new opcode, ZEND_DECLARE_ATTRIBUTED_CONST
, that phpdbg will ignore the same way it ignores ZEND_DECLARE_CONST
.
To Opcache
The JIT currently has logic to emit deprecation messages for constants that are deprecated; to avoid duplicating the new logic to check a constant's attributes for a #[\Deprecated]
attribute, that logic is centralized in a new zend_deprecated_constant()
function.
To Reflection
New method ReflectionConstant::getAttributes()
is added, with a signature to match the other such methods for retrieving attributes:
final class ReflectionConstant implements Reflector { // Everything that currently exists // ... public function getAttributes(?string $name = null, int $flags = 0): array {} }
Additionally, code that expects ReflectionConstant::isDeprecated()
to always return false
for userland constants will need to be updated, since it can now be true.
New Constants
Attribute::TARGET_CONSTANT
indicates that an attribute can be applied to compile-time non-class constants.
Unaffected PHP Functionality
Existing uses of attributes or constants - previously, trying to add an attribute to a constant would have generated an error, so any existing working current code should continue to work as expected.
Future Scope
Adding support to non-compile-time non-class constants, via define()
.
Proposed Voting Choices
This vote requires a 2/3 majority to adopt.
Patches and Tests
Implementation
After the project is implemented, this section should contain
- the version(s) it was merged into
- a link to the git commit(s)
- a link to the PHP manual entry for the feature
- a link to the language specification section (if any)
References
Changelog
0.2:
- Improved discussion of backward incompatible changes