Table of Contents

PHP RFC: Attributes on Constants

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

To the list of current valid targets (see attribute_syntax):

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

https://github.com/php/php-src/pull/16952

Implementation

After the project is implemented, this section should contain

  1. the version(s) it was merged into
  2. a link to the git commit(s)
  3. a link to the PHP manual entry for the feature
  4. a link to the language specification section (if any)

References

Changelog

0.2: