The Support Closures in constant expressions RFC added support for Closures in constant expressions. The RFC left supporting “First Class Callables” (“FCC”), which can be considered syntax sugar for creating a Closure that just forwards any calls to the callable in question.
Given that FCCs effectively act as syntax sugar, the same use cases as with Closures themselves also apply to this RFC. It is intended to round off the “Closures in constant expressions” RFC.
This RFC proposes that it shall be legal to use the FCC syntax in constant expressions. The semantics match the existing semantics of FCCs and of constant expressions. Aside from the obvious, this means:
new
-expressions in constant expressions.All the constraints imposed on FCCs outside of constant expressions naturally also apply to FCCs within constant expressions. Defining a FCC within a constant expression comes with the following additional constraints:
::
) are supported.function_name(...)
or ClassName::methodName(...)
references are supported. The function name must not be an expression (constant or otherwise). [ClassName::class, 'methodName'](...)
, (Constant)(...)
, or similar are not supported.__callStatic()
method on the referenced class are not supported.
As with other constant-expressions, FCC defined in constant expressions follow the expected scoping rules of the context they are placed in. This means that FCC in property default values may reference private
methods of the class where they are defined, similarly to how a FCC defined in the constructor and stored in a property may access those private
methods. Likewise are FCC in attribute parameters allowed to access private
methods of the surrounding class.
<?php #[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)] class Attr { public function __construct(public Closure $value) {} } #[Attr(self::myMethod(...))] #[Attr(strrev(...))] class C { private static function myMethod(string $foo) { return "XXX"; } } foreach ((new ReflectionClass(C::class))->getAttributes() as $reflectionAttribute) { $closure = $reflectionAttribute->newInstance()->value; var_dump($closure('abc')); } // Prints: // // string(3) "XXX" // string(3) "cba"
None. Using first class callables within constant expressions previously resulted in a compile-time error. Closures can appear within constant expressions since the Support Closures in constant expressions RFC.
Nevertheless, as with every RFC that changes what previously was a compile-time error to be valid PHP code, this RFC requires changes to static analyzers and IDEs to correctly understand the semantics of the code and not erroneously report errors.
Next 8.x (8.5).
None.
None.
The current implementation uses a special AST structure to cache the resolved function for consistent behavior of the global function fallback. To correctly cache this AST structure, Opcache changes are required. The PR passes all tests both with and without JIT enabled.
None.
None.
None.
Only constant expression are affected by this change, but Closures could already appear within them.
None.
After the project is implemented, this section should contain
n/a