[PHP-DEV] Should there be a `get_declared_enums()` function ?

L.S.,

I just noticed the following, which struck me as weird/inconsistent:

There are four different OO structures in PHP:

  1. Classes
  2. Interfaces
  3. Traits
  4. Enums

For all four, an *_exists() function is available, i.e. class_exists(), interface_exists(), trait_exists() and enum_exists() [2].

But only for three out of the four, a get_declared_*() function exists.
There is get_declared_classes(), get_declared_interfaces(), get_declared_traits(), but no get_declared_enums() [2].

I’m aware that enums are internally considered classes and that get_declared_classes() will retrieve them [1], but the same could be said about interfaces and traits, yet they do have their own get_declared_*() function.

Should a get_declared_enums() function be added ?
And should the get_declared_classes() function be adjusted to exclude enums ?

I did check the enum RFC [3], but I couldn’t find any mention or discussion about this in the RFC.

Smile,
Juliette

1: https://3v4l.org/0ub6I
2: https://www.php.net/manual/en/ref.classobj.php
3: https://wiki.php.net/rfc/enumerations

On Wed, Aug 14, 2024, at 8:51 PM, Juliette Reinders Folmer wrote:

L.S.,

I just noticed the following, which struck me as weird/inconsistent:

There are four different OO structures in PHP:
1. Classes
2. Interfaces
3. Traits
4. Enums

For all four, an `*_exists()` function is available, i.e.
`class_exists()`, `interface_exists()`, `trait_exists()` and
`enum_exists()` [2].

But only for three out of the four, a `get_declared_*()` function
exists.
There is `get_declared_classes()`, `get_declared_interfaces()`,
`get_declared_traits()`, but no `get_declared_enums()` [2].

I'm aware that enums are internally considered classes and that
`get_declared_classes()` will retrieve them [1], but the same could be
said about interfaces and traits, yet they do have their own
`get_declared_*()` function.

Should a `get_declared_enums()` function be added ?
And should the `get_declared_classes()` function be adjusted to exclude enums ?

I did check the enum RFC [3], but I couldn't find any mention or
discussion about this in the RFC.

Smile,
Juliette

1: Online PHP editor | output for 0ub6I
2: PHP: Classes/Object Functions - Manual
3: PHP: rfc:enumerations

Conext: I can't remember the last time I used get_declared_classes() (thanks to autoloading and class_exists() it's a kinda pointless function), so when we were working on enums it never occurred to us to think about it. It wasn't a deliberate decision to omit, as far as I recall.

I think I'd be open to adding it; my concern would be the overlap with get_declared_classes(), which as you note currently would include enums, and changing that is a BC break (even if a tiny one that I doubt would impact anyone).

--Larry Garfield

Thanks for the response. It was exactly a (custom) autoloader situation which caused me to start wondering about this.

···

On 15-8-2024 15:09, Larry Garfield wrote:

On Wed, Aug 14, 2024, at 8:51 PM, Juliette Reinders Folmer wrote:

L.S.,

I just noticed the following, which struck me as weird/inconsistent:

There are four different OO structures in PHP:
1. Classes
2. Interfaces
3. Traits
4. Enums

For all four, an `*_exists()` function is available, i.e. 
`class_exists()`, `interface_exists()`, `trait_exists()` and 
`enum_exists()` [2].

But only for three out of the four, a `get_declared_*()` function 
exists.
There is `get_declared_classes()`, `get_declared_interfaces()`, 
`get_declared_traits()`, but no `get_declared_enums()` [2].

I'm aware that enums are internally considered classes and that 
`get_declared_classes()` will retrieve them [1], but the same could be 
said about interfaces and traits, yet they do have their own 
`get_declared_*()` function.

Should a `get_declared_enums()` function be added ?
And should the `get_declared_classes()` function be adjusted to exclude enums ?

I did check the enum RFC [3], but I couldn't find any mention or 
discussion about this in the RFC.

Smile,
Juliette

1: [https://3v4l.org/0ub6I](https://3v4l.org/0ub6I)
2: [https://www.php.net/manual/en/ref.classobj.php](https://www.php.net/manual/en/ref.classobj.php)
3: [https://wiki.php.net/rfc/enumerations](https://wiki.php.net/rfc/enumerations)

Conext: I can't remember the last time I used get_declared_classes() (thanks to autoloading and class_exists() it's a kinda pointless function), so when we were working on enums it never occurred to us to think about it.  It wasn't a deliberate decision to omit, as far as I recall.

I think I'd be open to adding it; my concern would be the overlap with get_declared_classes(), which as you note currently would include enums, and changing that is a BC break (even if a tiny one that I doubt would impact anyone).

--Larry Garfield

On Wed, Aug 14, 2024, at 8:51 PM, Juliette Reinders Folmer wrote:
Should a `get_declared_enums()` function be added ?

My answer is "very much, yes."

On Aug 15, 2024, at 9:09 AM, Larry Garfield <larry@garfieldtech.com> wrote:
Context: I can't remember the last time I used get_declared_classes() (...it's a kinda pointless function)

Your experience is one data point. Another data point is my experience that it is fortunate that `get_declared_classes()` exists as I find it to be a very a useful function. The core library I use for most projects depends on it for class initialization.

Your comment made me curious to see if others use it, and there are 8.1k uses on GitHub:

- Code search results · GitHub

Here is how I have used, in a greatly simplified example:

function autoload($class) {
   $classCount = count(get_declared_classes());
   if (!file_exists("src/{$class}.php")) {
     return;
   }
   include_once "src/{$class}.php";
   foreach (get_declared_classes() as $class) {
     if (!method_exists($class,'init')) {
       continue;
     }
     $class::init();
   }
}

As an aside, for this use-case I have always wanted PHP to add both 1.) a `get_declared_class_count()` function and 2) optional parameters for `get_declared_classes()` that would allow requesting a subset of classes, such as just the newly added classes. How important this is depends on if PHP maintains that array internally and just returns a reference, or if it instantiates memory and populates the array of classes to return every time the function is called.

, so when we were working on enums it never occurred to us to think about it. It wasn't a deliberate decision to omit, as far as I recall.

I think I'd be open to adding it; my concern would be the overlap with get_declared_classes(), which as you note currently would include enums, and changing that is a BC break (even if a tiny one that I doubt would impact anyone).

Add another parameter — or include as part of the args array — something like this (though I am sure this could be bikeshed to be better):

get_declared_classes(DeclaredClasses:ONLY_CLASSES, ['starting_from'=>174]);
get_declared_classes(DeclaredClasses:ALL, ['recently_declared'=>3]);

Or even:

DeclaredSymbols::get_classes([$args]) <-- returns only classes, not enums
DeclaredSymbols::get_enums([$args])
DeclaredSymbols::get_interfaces([$args])
DeclaredSymbols::get_traits([$args])
#fwiw

On Aug 16, 2024, at 12:23 AM, Juliette Reinders Folmer <php-internals_nospam@adviesenzo.nl> wrote:
Thanks for the response. It was exactly a (custom) autoloader situation which caused me to start wondering about this.

Seems Juliette's use-case may be at least somewhat similar to mine.

-Mike

Hey Juliette,

Should a get_declared_enums() function be added ?

Yes

And should the get_declared_classes() function be adjusted to exclude enums ?

No

You listed these entities: classes, interfaces, traits and enums.
But while there is a clear differentiation between what is considered a class, an interface or a trait, enums are just a subtype of classes.
“all enums are classes, but not all classes are enums.”

So for keeping this valid, get_declared_classes() should return all classes (including enums).
While get_declared_enums() should return all enums.

If one really wants all classes except enums, they could use array_diff(get_declared_classes(), get_declared_enums().
This would avoid the backward compatibility issues that Larry also mentioned.

Regards,
Alex

On 15.08.2024 at 03:51, Juliette Reinders Folmer wrote:

Should a `get_declared_enums()` function be added ?

Here we go:

    function get_declared_enums() {
        $enums = ;
        $exts = get_loaded_extensions(false);
        foreach ($exts as $ext) {
            $re = new ReflectionExtension($ext);
            $classes = $re->getClasses();
            foreach ($classes as $class) {
                if ($class->isEnum()) {
                    $enums = $class->name;
                }
            }
        }
        return $enums;
    }

Porting this to C is left as an excercise for the reader. :wink: Hint:
<php-src/Zend/zend_builtin_functions.c at 8853cf3ae950a1658054f286117bc8f77f724f00 · php/php-src · GitHub;

Note that the terminating folding marker is backwards.

And should the `get_declared_classes()` function be adjusted to exclude
enums ?

For reasons that have been stated elsewhere in this thread, I don't
think so.

Cheers,
Christoph

Porting this to C is left as an excercise for the reader. :wink: Hint:
<php-src/Zend/zend_builtin_functions.c at 8853cf3ae950a1658054f286117bc8f77f724f00 · php/php-src · GitHub;

I went ahead and created PR ext/standard: Add `get_declared_enums` function by Ayesh · Pull Request #15443 · php/php-src · GitHub
along with tests, UPGRADE notice, etc.

I think having a `get_declared_enums` function will be helpful. The
implementation is simple and straightforward too.

Should a get_declared_enums() function be added ?

Here we go:

function get_declared_enums() {
$enums = ;
$exts = get_loaded_extensions(false);
foreach ($exts as $ext) {
$re = new ReflectionExtension($ext);
$classes = $re->getClasses();
foreach ($classes as $class) {
if ($class->isEnum()) {
$enums = $class->name;
}
}
}
return $enums;
}

Porting this to C is left as an excercise for the reader. :wink: Hint:
<https://github.com/php/php-src/blob/8853cf3ae950a1658054f286117bc8f77f724f00/Zend/zend_builtin_functions.c#L1371-L1399>

Note that the terminating folding marker is backwards.

And should the get_declared_classes() function be adjusted to exclude
enums ?

For reasons that have been stated elsewhere in this thread, I don’t
think so.

And here is a one liner:

function get_declared_enums() {
return array_filter(get_declared_classes(), ‘enum_exists’);
}

On 16.08.2024 at 17:11, Nicolas Grekas wrote:

Should a `get_declared_enums()` function be added ?

Here we go:

    function get_declared_enums() {
        $enums = ;
        $exts = get_loaded_extensions(false);
        foreach ($exts as $ext) {
            $re = new ReflectionExtension($ext);
            $classes = $re->getClasses();
            foreach ($classes as $class) {
                if ($class->isEnum()) {
                    $enums = $class->name;
                }
            }
        }
        return $enums;
    }

And here is a one liner:

    function get_declared_enums() {
         return array_filter(get_declared_classes(), 'enum_exists');
    }

Nice!

Are you suggesting that there is no need for get_declared_enums() in the
core, since it can be implemented in userland with a single function call?

If so, I still would argue that it makes sense to implement the function
in the core for (a) consistency, and (b) performance reasons.

Cheers,
Christoph

On 16.08.2024 at 17:01, Ayesh Karunaratne wrote:

Porting this to C is left as an excercise for the reader. :wink: Hint:
<php-src/Zend/zend_builtin_functions.c at 8853cf3ae950a1658054f286117bc8f77f724f00 · php/php-src · GitHub;

I went ahead and created PR ext/standard: Add `get_declared_enums` function by Ayesh · Pull Request #15443 · php/php-src · GitHub
along with tests, UPGRADE notice, etc.

Thank you very much!

I think having a `get_declared_enums` function will be helpful. The
implementation is simple and straightforward too.

I concur.

Christoph

On Fri, 16 Aug 2024, 16:46 Christoph M. Becker, <cmbecker69@gmx.de> wrote:

On 16.08.2024 at 17:11, Nicolas

And here is a one liner:

function get_declared_enums() {
return array_filter(get_declared_classes(), ‘enum_exists’);
}

Nice!

Are you suggesting that there is no need for get_declared_enums() in the
core, since it can be implemented in userland with a single function call?

I think he just compulsively golfs inefficient PHP code (I have the same affliction).

Cheers,
Bilge

On Fri, 16 Aug 2024, 16:46 Christoph M. Becker, <cmbecker69@gmx.de> wrote:

On 16.08.2024 at 17:11, Nicolas

And here is a one liner:

function get_declared_enums() {
return array_filter(get_declared_classes(), ‘enum_exists’);
}

Nice!

Are you suggesting that there is no need for get_declared_enums() in the
core, since it can be implemented in userland with a single function call?

I think he just compulsively golfs inefficient PHP code (I have the same affliction).

Possibly :smiley:

I shared this as food for thoughts. I’m not convinced this function would be useful personally, but that’s not really an argument :wink:

To everyone on this thread and thus nobody in specific (hence my top post):

Given that get_declared_*() populates a new ZEND_HASH each time the function is called[1] — which for classes can easily be hundreds of strings — would there be any appetite to:

1. Add an optional parameter — e.g. `get_declared_classes($startingFrom)` — that can limit the number of symbols starting with "n" where if n==100 then it would return array_slice($symbols,100), and

2. Add a function — `get_declared_class_count()` — that returns the current number of declared symbols of whichever kind of symbol, so we can get the "n" before calling `include`/`require` to use with get_declared_*() after calling `include`/`require`?

Used in a (very simplistic) example:

function autoload($class) {
   $startingFrom = get_declared_class_count();
   if (!file_exists("src/{$class}.php")) {
     return;
   }
   include_once "src/{$class}.php";
   foreach (get_declared_classes($startingFrom) as $class) {
     if (!method_exists($class,'init')) {
       continue;
     }
     $class::init();
   }
}

This would cut down on creating hashes with 100+ strings that get immediately thrown away, and also cut down on memory fragmentation/garbage collector churn.

-Mike

[1] php-src/Zend/zend_builtin_functions.c at 18d41502da0da1bb3928e60c41f1b821974c2c01 · php/php-src · GitHub

On Aug 16, 2024, at 7:13 AM, Christoph M. Becker <cmbecker69@gmx.de> wrote:

On 15.08.2024 at 03:51, Juliette Reinders Folmer wrote:

Should a `get_declared_enums()` function be added ?

Here we go:

   function get_declared_enums() {
       $enums = ;
       $exts = get_loaded_extensions(false);
       foreach ($exts as $ext) {
           $re = new ReflectionExtension($ext);
           $classes = $re->getClasses();
           foreach ($classes as $class) {
               if ($class->isEnum()) {
                   $enums = $class->name;
               }
           }
       }
       return $enums;
   }

Porting this to C is left as an excercise for the reader. :wink: Hint:
<php-src/Zend/zend_builtin_functions.c at 8853cf3ae950a1658054f286117bc8f77f724f00 · php/php-src · GitHub;

Note that the terminating folding marker is backwards.

And should the `get_declared_classes()` function be adjusted to exclude
enums ?

For reasons that have been stated elsewhere in this thread, I don't
think so.

Cheers,
Christoph

Thanks for creating the PR Ayesh!

I’m presuming it’s too late for PHP 8.4, what with feature freeze having come & gone this week.

Based on the mostly supportive responses on the list, I wonder whether an RFC is needed. If so, I’d be happy to create an initial draft (for PHP 8.5).

Smile,
Juliette

Mike,

While your suggestion does not directly relate to what triggered my mail to the list, I very very much like the idea.

It’s as if you are reading my mind or rather, reading one of the autoloaders [1] I need to maintain, in which your above outlined proposal should definitely make for more efficiency.

Having said that, the same parameter + extra function would then also be needed for get_declared_interfaces(), get_declared_traits() - and, if it would be added, get_declared_enums().

There is one problem I can see with this approach though: since PHP 7.4, the return value of get_declared_classes() (and friends) does not guarantee any particular order anymore [2].
So, an array_slice($symbols, $n) may not get you the latest classes loaded, so I think this would only work if the order of classes is guaranteed in some way.

Smile,
Juliette

1: https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/6fbbc1078094d905f0773421f13830744a144d1e/autoload.php#L153-L247
2: https://www.php.net/manual/en/function.get-declared-classes.php#refsect1-function.get-declared-classes-changelog

I'm presuming it's too late for PHP 8.4, what with feature freeze having come & gone this week.

Based on the mostly supportive responses on the list, I wonder whether an RFC is needed. If so, I'd be happy to create an initial draft (for PHP 8.5).

Thank you!

We now have the Release Cycle Update RFC approved
(PHP: rfc:release_cycle_update),
and it does allow minor new features during the beta period.

Quoting from the RFC:

[snip]
It therefore seems illogical to allow RFC-requiring features to be merged during the beta period, but not minor improvements that do not require an RFC, such as adding constant, parameters, config options, or even small functions or methods.

We propose to explicitly allow minor features, optimizations, and internal API / ABI changes, during the beta period.

I think the `get_declared_enums` is small enough to be considered a
minor change given we don't change any engine internals. Given the
positive response on the mailing list, I think we can have this in PHP
8.4 as well, subject to RMs approval of course. There's also a PR from
yesterday (GH-15440: adding CURLOPT_TCP_KEEPCNT constant (8.9.0) by devnexen · Pull Request #15446 · php/php-src · GitHub) that added a new
Curl constant.

Hi Juliette,

On Aug 16, 2024, at 9:25 PM, Juliette Reinders Folmer <php-internals_nospam@adviesenzo.nl> wrote:

On 17-8-2024 2:00, Mike Schinkel wrote:

To everyone on this thread and thus nobody in specific (hence my top post):

Given that get_declared_*() populates a new ZEND_HASH each time the function is called[1] — which for classes can easily be hundreds of strings — would there be any appetite to:

1. Add an optional parameter — e.g. `get_declared_classes($startingFrom)` — that can limit the number of symbols starting with "n" where if n==100 then it would return array_slice($symbols,100), and

2. Add a function — `get_declared_class_count()` — that returns the current number of declared symbols of whichever kind of symbol, so we can get the "n" before calling `include`/`require` to use with get_declared_*() after calling `include`/`require`?

This would cut down on creating hashes with 100+ strings that get immediately thrown away, and also cut down on memory fragmentation/garbage collector churn.

-Mike

[1]
php-src/Zend/zend_builtin_functions.c at 18d41502da0da1bb3928e60c41f1b821974c2c01 · php/php-src · GitHub

Mike,

While your suggestion does not directly relate to what triggered my mail to the list, I very very much like the idea.

Excellent!

It's as if you are reading my mind or rather, reading one of the autoloaders [1] I need to maintain, in which your above outlined proposal should definitely make for more efficiency.

Thank you for sharing that. Yes, your use-case is very similar to mine.

Having said that, the same parameter + extra function would then also be needed for `get_declared_interfaces()`, `get_declared_traits()` - and, if it would be added, `get_declared_enums()`.

That was my assumption and intention, but I did not say so explicitly. I should have.

Thanks to Ayesh's excellent PR, I was able to recognize that all of those functions in-fact are implemented via one internal function `get_declared_class_impl()` so it only made sense — to me, at least — that modifying it would enable the same functionality for all four (4) userland functions.

There is one problem I can see with this approach though: since PHP 7.4, the return value of `get_declared_classes()` (and friends) does not guarantee any particular order anymore [2].
So, an `array_slice($symbols, $n)` may not get you the _latest_ classes loaded, so I think this would only work if the order of classes is guaranteed in some way.

That is a super relevant insight and one I was actually not aware of.

Do you happen to know if it was triggered by an explicit RFC to that effect, or if it resulted because of a side-effect of some other implementation change? From my perspective, that is definitely a BC break and one that I am surprised I never noticed before? Do you also know if it is a case of "not guaranteed, but in-fact actual fact it always works that way, or not?"

I have not used my lib that needs that functionality to work in a few years, so maybe it is broken now and those who are now maintaining those apps have had to deal with it?

Given that you see value in the same use-case I had which was an autoloader, maybe it would be better to achieve the functionality we need in a different, more efficient way?

What if instead PHP were to implement an optional 2nd callback parameter to `include()` / `require()` / `include_once()` / `require_once()` to allow us to capture the symbols loaded and their paths? The callback function could return `void` and accept an array of `$symbols` with the following guaranteed minimum structure?

$symbols = array(
   'classes' => ,
   'interfaces' => ,
   'traits' => ,
   'enums' => ,
);

With that you could reimplement all that PHP code you linked — at least for versions of PHP supporting the callback — to look like this:

function loadFile($path)
{
   if (strpos(__DIR__, 'phar://') !== 0) {
     $path = realpath($path);
     if ($path === false) {
       return false;
     }
   }
   if (isset(self::$loadedClasses[$path]) === true) {
     return self::$loadedClasses[$path];
   }
   include($path, function($symbols) use ($path) {
     foreach ($symbols['classes'] as $className) {
       self::$loadedClasses[$path] = $className;
       self::$loadedFiles[$className] = $path;
     }
   });
   return self::$loadedClasses[$path];
}//end loadFile()

This approach would be a less disruptive than my prior suggestion which would have added four (4) new `*_count()` functions and new optional parameters for four (4) existing function vs. this proposal which just adds new optional parameters for four (4) other existing functions. Further, and the signature(s) required for parameters would be much easier to settle on.

I checked the code[2] and if I understand it correctly would (only?) require adding a Zend Observer[3] callback to be notified in `zend_bind_class_in_slot()` although I still cannot figure out where that observer would need to be added.

Going this approach would also make the userland code in PHPCodeSniffer a lot more efficient than the code you currently must run for every included file simply to determine what symbols were loaded.

What do you think if this alternate approach?

-Mike

[1] php-src/Zend/zend_builtin_functions.c at 18d41502da0da1bb3928e60c41f1b821974c2c01 · php/php-src · GitHub
[2] php-src/Zend/zend_compile.c at php-8.3.10 · php/php-src · GitHub
[3] Zend Event Manager vs Observer Pattern in PHP

Hi Mike,

There is one problem I can see with this approach though: since PHP 7.4, the return value of `get_declared_classes()` (and friends) does not guarantee any particular order anymore [2].
So, an `array_slice($symbols, $n)` may not get you the _latest_ classes loaded, so I think this would only work if the order of classes is guaranteed in some way.

That is a super relevant insight and one I was actually not aware of.

Do you happen to know if it was triggered by an explicit RFC to that effect, or if it resulted because of a side-effect of some other implementation change?

I honestly don’t know, but if I look through the PHP 7.4 RFC list, I have a niggling suspicion it may have something to do with the Preloading RFC [1] ? I may very well be wrong though.

From my perspective, that is definitely a BC break and one that I am surprised I never noticed before?  Do you also know if it is a case of "not guaranteed, but in-fact actual fact it always works that way, or not?"

Well, for the autoloader I previously linked to [2], it was a problematic change which we did have to work around, see [3] and [4] for details of the issues we saw (parent class vs child class order reversals, issues when multiple classes were declared in one file).

I haven’t deep-dived into the order change, other than to validate the reported issues and proposed fixes.

What if instead PHP were to implement an optional 2nd callback parameter to `include()` / `require()` / `include_once()` / `require_once()` to allow us to capture the symbols loaded and their paths? The callback function could return `void` and accept an array of `$symbols` with the following guaranteed minimum structure?

$symbols = array(
   'classes' => [],
   'interfaces' => [],
   'traits' => [],
   'enums' => [],
);

Except include() and friends aren’t function calls, but language constructs/expressions and don’t take parameters as such, so I don’t see how that would be possible without changing include() and friends to function calls (along the lines of what happened for exit in PHP 8.4 with non-parenthesized use still possible to mitigate the otherwise huge breaking change), or alternatively, introducing wrapper functions for the language constructs - so no change to the existing functionality, but new functions with a signature along the lines of include_and_get_symbols( $path ): array with the return value being the symbols loaded from $path.

This approach would be a less disruptive than my prior suggestion

Not so sure about that considering the above :wink:

What do you think if this alternate approach?

This probably needs some more bike shedding :wink:

Smile,
Juliette

1: https://wiki.php.net/rfc/preload
2: https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/6fbbc1078094d905f0773421f13830744a144d1e/autoload.php#L153-L247
3: https://github.com/squizlabs/PHP_CodeSniffer/pull/3130
4: https://github.com/squizlabs/PHP_CodeSniffer/issues/3145

On 17-8-2024 6:26, Ayesh Karunaratne wrote:

I think the get_declared_enums is small enough to be considered a minor change given we don’t change any engine internals. Given the positive response on the mailing list, I think we can have this in PHP 8.4 as well, subject to RMs approval of course.

I’ll keep my fingers crossed :wink:

On Fri, Aug 16, 2024, at 7:53 PM, Juliette Reinders Folmer wrote:

On 16-8-2024 17:01, Ayesh Karunaratne wrote:

I went ahead and created PR ext/standard: Add `get_declared_enums` function by Ayesh · Pull Request #15443 · php/php-src · GitHub along with tests, UPGRADE notice, etc. I think having a `get_declared_enums` function will be helpful. The implementation is simple and straightforward too.

Thanks for creating the PR Ayesh!

I'm presuming it's too late for PHP 8.4, what with feature freeze
having come & gone this week.

Based on the mostly supportive responses on the list, I wonder whether
an RFC is needed. If so, I'd be happy to create an initial draft (for
PHP 8.5).

Smile,
Juliette

I would prefer to have an RFC for this, even if it's short. I'm not against it, I just think there's enough non-trivial questions (eg, impact on get_declared_classes()) that it warrants an RFC process/discussion.

--Larry Garfield