Skip to content

Language: __clone magic method — invoke user hook on clone (Zend parity) #3170

Description

@PurHur

Category

language

Problem

clone $obj lowers to TYPE_CLONE and copies the object shell, but __clone() is never called. Zend runs the magic method after the shallow copy so objects can deep-copy or adjust state.

Today VM only does cloneShallow():

                case OpCode::TYPE_CLONE:
                    $result = $frame->scope[$op->arg1];
                    $src = $frame->scope[$op->arg2]->resolveIndirect();
                    if (Variable::TYPE_OBJECT !== $src->type) {
                        throw new \LogicException('clone requires an object');
                    }
                    $result->object($src->toObject()->cloneShallow());
                    break;

php-src reference

  • Zend/zend_objects.c — zend_objects_clone_obj(), zend_std_clone_object()
  • Zend/zend_compile.c — clone opcode emits call to __clone when present

Repro

./script/docker-exec.sh -- bash -lc 'php bin/vm.php -r "
class C { public int \$x = 1; public function __clone() { \$this->x = 2; }
}
\$a = new C(); \$b = clone \$a; echo \$b->x;
"'
# this compiler: 1
# Zend PHP:     2

Zend reference:

php -r 'class C { public int $x = 1; public function __clone() { $this->x = 2; } } $a = new C(); $b = clone $a; echo $b->x;'

Scope (this repo)

Area Files
Compiler lib/Compiler.php — optional TYPE_METHOD_CALL after clone when class defines __clone
VM lib/VM.php TYPE_CLONE, lib/VM/ObjectEntry.php
JIT lib/JIT.php / lib/JIT/Builtin/Type/Object_.php — mirror VM hook order
AOT lib/AOT/ if clone op used on self-host path
Tests test/compliance/cases/oop/clone_magic.phpt

Done when

  • Repro prints 2 under bin/vm.php, bin/jit.php (or documented JIT deferral in matrix), and AOT fixture if clone used in inventory.
  • php script/capability-syntax.php row for __clone updated (or new row).
  • No regression on shallow clone without __clone.

Notes

  • Shallow clone + __clone dispatch is separate from JIT: clone expression lowering (object copy) #1223 (clone JIT opcode exists); this issue is magic method semantics.
  • Parent __clone chaining (parent::__clone()) follows normal method dispatch once hook runs.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:compilerCompiler / CFG / JITarea:vmVirtual machineenhancementNew feature or requestimplementation-readySpec complete: repro, php-src ref, done-when — safe for workers to claimphase-2:languagePhase 2 – language features

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions