# RFC: Attributes on Constants

- Status: Implemented (PHP 8.5)
- Authors: Daniel Scherzer, daniel.e.scherzer@gmail.com
- Date: 2024-11-30
- Version: 0.2
- Implementation: https://github.com/php/php-src/pull/16952
- Original: https://wiki.php.net/rfc/attributes-on-constants
- Page: https://externals.io/rfc/attributes-on-constants
- More for agents: search with https://externals.io/search.md?q={query} · RFCs at https://externals.io/rfc.md · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

## Votes

### Support attributes on constants (closed)

Yes: 26 · No: 0

Voters: alcaeus (Yes), asgrim (Yes), ashnazg (Yes), ayesh (Yes), bwoebi (Yes), cpriest (Yes), crell (Yes), derick (Yes), galvao (Yes), girgias (Yes), heiglandreas (Yes), josh (Yes), kalle (Yes), kinncj (Yes), mcmic (Yes), nicolasgrekas (Yes), nielsdos (Yes), ocramius (Yes), petk (Yes), pierrick (Yes), ramsey (Yes), santiagolizardo (Yes), sergey (Yes), sirsnyder (Yes), theodorejb (Yes), timwolla (Yes)

## Discussions on the mailing list

- [\[RFC\] \[Discussion\] Attributes on compile-time constants](https://externals.io/message/126084.md) — started on 2024-11-30, 5 messages
- [\[VOTE\] Attributes on Constants](https://externals.io/message/126126.md) — started on 2024-12-16, 3 messages

---

## Introduction

Attributes were first introduced in [attributes\_v2](https://externals.io/rfc/attributes_v2), with the current syntax adopted [shorter\_attribute\_syntax\_change](https://externals.io/rfc/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](https://externals.io/rfc/attributes_v2#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:

```php
// 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:

```php
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

Voting started on 2024-12-16 and will end on 2025-01-06 00:00:00 UTC.

This vote requires a 2/3 majority to adopt.

**Vote: Support attributes on constants** — Yes: 26 · No: 0 (closed)

## 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

- [attributes\_v2](https://externals.io/rfc/attributes_v2)
- [shorter\_attribute\_syntax\_change](https://externals.io/rfc/shorter_attribute_syntax_change)
- <https://github.com/php/php-src/pull/16952>

## Changelog

0.2:

- Improved discussion of backward incompatible changes

0.1:

- Initial proposal
