Hi internals, It's been a few years since I originally brought up the named parameters RFC: https://wiki.php.net/rfc/named_params
This topic has recently come up as part of https://externals.io/message/109220 again, in particular with the observation that the combination of constructor parameter promotion and named parameters will give us, as a side-effect, an ergonomic object initialization syntax that is well-integrated with the remainder of the language. I've reimplemented basic named param support for master in https://github.com/php/php-src/pull/5357, but before going any further here, I want to restart discussion on the various open issues that the named parameter concept in PHP has. I think there's two primary issues: ## LSP checks for parameter names Parameter names currently have no particular significance in PHP, only their position in the signature is important. If named parameters are introduced (in a way that does not require opt-in at the declaration-site), then parameter names become significant. This means that changing a parameter name during inheritance constitutes an LSP violation (for non-constructor methods). There are a number of ways in which this issue may be approached: 1. Silently ignore the problem. No diagnostic is issued when a parameter name is changed during inheritance. An error exception will be thrown when trying to use the (now) unknown parameter name. 2. Throw a notice if a parameter name is changed. While LSP violations are normally fatal errors (in PHP 8), we could use a lower-severity diagnostic for this case, that allows code to still run, but makes developers aware of the problem. (It should be noted that automatic fixup of parameter names using tooling should be fairly easy to implement.) 3. Allow using parameter names from the parent method, even if they have been renamed. This makes things "just work", but seems fairly magic, and has edge cases like a signature foo($a, $b) being changed to foo($b, $a), where it's not possible to implicitly support both at the same time. 4. Make named-parameter opt-in in some fashion, so that parameter names only need to be preserved for methods that have the opt-in marker. I'm not a fan of this, as it greatly diminishes the practical usefulness of named parameters. ## Internal functions There are two problems when it comes to named parameters and internal functions. The first is that the internal parameter names do not always match the parameter names in the documentation. This is nothing we can't solve (in a hopefully mostly automated way), but is work that needs to be done. The larger problem is that internal functions don't have a well-defined concept of parameter default value. Parameter defaults are implicit in C code, and sometimes based on argument count checks. When named parameters are involved, one generally cannot assume that if a later (optional) parameter is passed, all earlier (optional) parameters are passed as well. While it is possible (but rather challenging) to make things work mostly transparently with current ZPP, some functions do need to adjusted to support named parameters, and may cause misbehavior/crashes if they are not. As a rule of thumb, functions that make non-trivial use of ZEND_NUM_ARGS() are affected. This is something we can address for functions in bundled extensions, but may also affect 3rd-party extensions. I think that ideally, we'd deal with internal functions the same way we do for userland functions, by relying on default values that are part of the function declaration. As part of the PHP stub work, we now have information on default values in stub files, but this information is currently not available to the engine. Máté Kocsis has been working on getting this information exposed in Reflection, see https://github.com/php/php-src/pull/5353. In the current form, accessing these defaults is fairly inefficient, but maybe with some caching, we could base named parameters on this information: If there are no "gaps" in the passed parameters, then named parameters will always work. If an optional parameter is not specified, but a later parameter is, then we will fetch the default value for that parameter, and pass it instead. If the parameter is optional, but has no well-defined default (UNKNOWN in stubs), then the call is not permitted (Error: "Cannot skip parameter $foo with unknown default value", or similar.) Any thoughts on these issues, or named parameters in general would be welcome. Regards, Nikita