rfc:deprecated_attribute

PHP RFC: #[\Deprecated] Attribute

Introduction

PHP’s internal functions can be marked as deprecated, making this information available to Reflection and emitting deprecation errors, but there is equivalent functionality for functions defined in userland.

While the functionality can be emulated using trigger_error() to emit a E_USER_DEPRECATED error when calling a method and either parsing a doc comment for the @deprecated annotation or attaching a custom-defined attribute and reading either one with Reflection, it requires special handling for internal and userland functions respectively: ReflectionFunctionAbstract::isDeprecated() always returns false for userland functions.

Proposal

Developers can put an attribute #[Deprecated] on the following elements (targets):

  • Functions
  • Methods

For now is not possible to target classes, constants, properties or arguments with this attribute, and it is left for future RFC(s) to address this.

When this attribute is present, during the compile step the existing “ZEND_ACC_DEPERACTED” function flag is added to the op_array (userland function), which will lead to a deprecation warning when the function is called at runtime, with only minimal changes in the VM.

The ZEND_ACC_DEPRECATED flag and behavior is present for internal functions already. The presence of a Deprecated attribute allows to expose this feature to userland functions/methods and closes a capability gap between internal and userland functions.

For userland functions the E_USER_DEPRECATED level is used, instead of the E_DEPRECATED that is raised for internal functions.

<?php
 
use Deprecated;
 
#[Deprecated]
function test() {}
// Deprecated: Function test() is deprecated
 
#[Deprecated("use test3() instead")]
function test2() {}
// Deprecated: Function test2() is deprecated, use test3() instead
 
class Foo {
    #[Deprecated]
    public function test() {}
    // Deprecated: Method Foo::test() is deprecated in %s
}

The deprecated class is final and cannot be extended. The reason for this is that the engine internally cannot autoload attributes, so checking for a subclass that extends the Deprecated class is not technically possible. Marking the class as final prevents that users extend the class and expect their children exhibit the same behavior.

Runtime Effects

Using the deprecated attribute on a function or method behaves the same as putting a call to trigger_error using E_DEPRECATED level as the first line of the same function/method.

While other languages have deprecation attributes, they usually generate compile time warnings instead of runtime warnings. However as PHP's current deprecation model is based on runtime warnings, the Deprecation attribute builds on that existing model. The benefit of a declarative approach with an attribute over the current approach with a function call to trigger_error is that is that it abstracts the implementation details of how deprecations work, with the potential for better integration with future changes to the runtime warning stack of PHP.

This feature adds a small bitmask check in the VM for every function call.

Changes to the runtime warning stack of PHP are out of the scope of this RFC.

Backward Incompatible Changes

Deprecated can no longer be used as a class name in the global namespace. A GitHub search for “class Override ” language:php symbol:override revealed a total of 318 matches in source code. Many of them appear within a comment. The actual class definition all appear to be defined within a namespace.

Proposed PHP Version(s)

Next minor (PHP 8.4).

RFC Impact

To SAPIs

None.

To Existing Extensions

None.

To Opcache

None.

New Constants

None.

php.ini Defaults

None.

Open Issues

Future Scope

  • Allowing #[\Deprecated] on classes or other targets of attributes
  • Adding further metadata to the Deprecated attribute beyond a custom message, such as hints for replacements that IDEs could use.

Proposed Voting Choices

Accept the #[\Deprecated] attribute as described?
Real name Yes No
Final result: 0 0
This poll has been closed.

Patches and Tests

Implementation

n/a

References

Rejected Features

n/a

rfc/deprecated_attribute.txt · Last modified: 2024/04/19 11:22 by timwolla