[php-src] Issue #9236: Partially support first-class callable syntax in constant expressions
| From: | pevdh | Date: | Tue, 02 Aug 2022 17:37:02 +0000 |
| Subject: | [php-src] Issue #9236: Partially support first-class callable syntax in constant expressions | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-242105@lists.php.net to get a copy of this message | ||
Issue: https://github.com/php/php-src/issues/9236
Author: pevdh
### Description
The first-class callable syntax is currently not allowed in constant expressions:
```php
class X {
const FN = strlen(...);
}
var_dump((X::FN)('test'));
// PHP Fatal error: Constant expression contains invalid operations
```
I propose partially supporting the first-class callable syntax in a constant expression.
Specifically, I propose that PHP allows these two cases in a constant context:
```php
class X {
const A = strlen(...);
const B = SomeClass::someStaticMethod(...);
}
```
While (still) disallowing expressions that cannot be known at compile time:
```php
class X {
const C = $closure(...);
const D = $obj->method(...);
const E = ($obj->property)(...);
// etc. See the first-class callables RFC for a complete list
}
```
## Example
Symfony's
Choice assertion allows the user to specify a callback. It would be nice
if we could use the first-class callable syntax in attributes, but this is currently not allowed:
```php
use Symfony\Component\Validator\Constraints as Assert;
class User {
#[Assert\Choice(callback: Role::values(...))] // Using this syntax here causes an error
public string $role;
}
enum Role: string
{
case Customer = 'customer';
case Admin = 'admin';
public static function values() {
return array_map(fn (Role $a) => $a->name, self::cases());
}
}
```
## Implementation
I hacked together [a working
patch](https://github.com/pevdh/php-src/commit/343ba93d66b720aa14f058773c023f2ca3326d85) that
supports the strlen(...) syntax in constant expressions. I haven't gotten around
to implementing SomeClass::someStaticFunction(...) yet. There are probably some edge
cases that I'm missing - I'm not too familiar with the PHP code base.
I'm also not sure if this feature would require an RFC. I would imagine it would, though.
Please let me know what you think.