Skip to content

Language: first-class callables yield Closure objects (#4810) - #4961

Merged
PurHur merged 1 commit into
masterfrom
agent/issue-4810-fcc-closure-object
Jun 3, 2026
Merged

PurHur merged 1 commit into
masterfrom
agent/issue-4810-fcc-closure-object

Conversation

@PurHur

@PurHur PurHur commented Jun 3, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add TYPE_FROM_CALLABLE so strlen(...), Class::m(...), and [$o,'m'](...) lower to real Closure instances via ClosureSupport::fromCallable (Zend zend_create_closure() parity).
  • JIT: FromCallableHelper wraps compile-time callables with closureCall proxies (no string/array invoke folding).
  • Fix is_object() VM path to resolveIndirect() so object checks match instanceof on boxed variables.

php-src reference: Zend/zend_compile.c (zend_compile_first_class_callable), Zend/zend_closures.c (zend_create_closure).

Verification

./script/docker-exec.sh -- bash -lc 'php test/tmp/repro-fcc-closure-object.php; php bin/vm.php test/tmp/repro-fcc-closure-object.php'
true
true
true
true
./script/docker-exec.sh -- bash -lc 'vendor/bin/phpunit --filter first_class_callable_closure_object 2>&1'
OK (2 tests, 2 assertions)
./script/docker-exec.sh -- bash -lc 'vendor/bin/phpunit --filter "VMTest::testCases.*first_class_callable[^_]" 2>&1'
OK (1 test, 1 assertions)

Closes #4810

Made with Cursor

Lower strlen(...), Class::m(...), and [$o,'m'](...) via TYPE_FROM_CALLABLE
using ClosureSupport::fromCallable on the VM and FromCallableHelper on JIT.
Resolve indirect values in is_object() so object checks match instanceof.

Co-authored-by: Cursor <cursoragent@cursor.com>
@PurHur
PurHur merged commit 2793246 into master Jun 3, 2026
@PurHur
PurHur deleted the agent/issue-4810-fcc-closure-object branch June 3, 2026 09:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Language: first-class callable (strlen(...), Foo::bar(...)) must yield Closure objects (zend_compile.c)

1 participant