Hi
Clarifying on the technical questions.
Am 2025-05-26 16:37, schrieb Nicolas Grekas:
I think the RFC is missing a few bits to be complete:
- making "clone" a function means suddenly a "use clone;" or a "\clone"
is
going to be needed to not get a perf hit, isn't it? But since $y =
clone
$x; is still going to be valid, how will this be handled? The RFC could
give some more hints on the topic.
The implementation of making clone a function matches that of making
`exit()` a function in PHP 8.4
(https://wiki.php.net/rfc/exit-as-function). Specifically, `clone` will
remain a keyword and any use of a bare `clone` will compile to a
fully-qualified call to the clone function, as if you would have written
`\clone()`. For the same reason it will remain impossible to define a
`clone()` function within a namespace. It will also be disallowed to use
`disable_functions=clone` (the same as with exit and die).
That `clone()` will become a function should be considered an
implementation detail. You might start seeing a `clone()` frame in your
stack traces, within `assert(false && clone($foo))` the `\clone()` call
will be fully-qualified in the error message output and error messages
might slightly change (e.g. when passing a non-object to clone). Other
than that, it should not be noticeable. Perhaps even the ZEND_CLONE
opcode will remain when using clone with a single-parameter (this is
similarly to the other optimization of “special functions”, such as
count() or sprintf()).
I have made the following changes to the RFC that should hopefully
clarify things:
https://wiki.php.net/rfc/clone_with_v2?do=diff&rev2%5B0%5D=1748270099&rev2%5B1%5D=1748272162&difftype=sidebyside
- writing code with a wide range of supported PHP versions means we'll
start using construct such as:
if (PHP_VERSION_ID>=80500) {
$b = 'clone'($a, [...]); // note 'clone' is a string here, so that
the
line is valid syntax on PHP <= 8.4
else {
// another code path for PHP 8.4
}
That's of course because "use clone", "\clone" or "clone($foo)" is
invalid
PHP syntax currently.
Only `use function clone;` is currently invalid syntax (and it will
remain invalid syntax, similarly to `use function exit;`). `clone($a)`
currently is a perfectly valid cloning statement (with redundant
parentheses) and `\clone($a)` is a valid call to a function called
`clone` that does not exist: https://3v4l.org/VB3j1
But as I said above, it is not necessary to change any existing code.
The RFC is clear on that: There are no backwards incompatible changes
regarding the usage. When finalizing the implementation, I'll make sure
to run some benchmarks to determine whether or not keeping the OPcode is
worth it for the “non-with” case, or whether making clone a “frameless”
function would bring any benefit. But making sure it runs fast is the
job of the engine, not the job of the PHP developer and generally
speaking performance characteristics can change even without RFCs.
It could make sense to tell about this and show an example like this
one in
the RFC.
Given that your question appears to be based on a misunderstanding, I
believe adding such an example to the RFC is not useful.
- what if one gives a mangled property in the array? clone($foo,
["\0Foo\0bar" => 123])
It could be useful to write something about this case and/or at least
have
a test case that shows how this should behave.
As the RFC specifies, clone-with behaves exactly like regular property
assignments. This means your example behaves like `$foo->{"\0Foo\0bar"}
= 123;` and thus will throw “Error: Cannot access property starting with
"\0"”. I have added a test to the implementation [1]. Adding that to the
RFC text itself is probably not useful to the average reader, since this
is not something they will encounter.
Best regards
Tim Düsterhus
[1]
https://github.com/TimWolla/php-src/pull/6/commits/6f55e142e55af013bed0f31d7dc1633ef8201bff