Skip to content

Language: AOT Closure::bindTo bound $this + scope (#27219) - #27221

Merged
PurHur merged 2 commits into
masterfrom
agent/issue-27219-aot-closure-bindto
Aug 3, 2026
Merged

PurHur merged 2 commits into
masterfrom
agent/issue-27219-aot-closure-bindto

Conversation

@PurHur

@PurHur PurHur commented Aug 3, 2026

Copy link
Copy Markdown
Owner

Summary

  • Free-closure bindTo lost Variable::closureCall, so bind() returned null and thin AOT aborted on invoke — recover the inner via the same single-candidate / lastClosureCallProxy fallback as Closure::call (Regression: AOT Closure::call prints empty — VM/JIT match Zend (Zend/zend_closures.c) #26872), stash ClosureWithBinding for FUNCCALL_EXEC_RETURN, and write the Native {closure}_N TARGET on the clone.
  • Do not propertyFetch/copy uninitialized IS_STATIC / IS_METHOD slots on free closures (segfault under thin AOT); set those flags from Variable metadata only.

Closes #27219

php-src reference

  • Zend/zend_closures.c — ZEND_METHOD(Closure, bindTo) / zend_closure_bind_to

PHP implementation

  • lib/JIT/ClosureBindHelper.php — fallback + clone TARGET/flags
  • lib/JIT/ClosureHelper.php — storeInvokeTarget trampoline
  • lib/JIT.php — attachBoundClosureInvokeMetadata

Test plan

  • Issue repro AOT prints 7 (private $x) matching Zend/VM/JIT
  • --repeat style: 10/10 matched
  • vendor/bin/phpunit --filter ClosureBindToAotProxyTest — OK (2 tests)
  • test/repro/maintainer_gap_aot_closure_bindto.php

Verification transcript

VM:7 JIT:7 AOT:7
matched 10/10
OK (2 tests, 8 assertions)

Made with Cursor

PurHur and others added 2 commits August 3, 2026 09:41
Free-closure bindTo lost Variable::closureCall across assigns, so bind()
returned null and thin AOT aborted on invoke. Recover the inner via the
same single-candidate / lastClosureCallProxy fallback as Closure::call,
stash ClosureWithBinding for FUNCCALL_EXEC_RETURN, and write the Native
{closure}_N TARGET on the cloned object for RuntimeIndirect dispatch.

Co-authored-by: Cursor <cursoragent@cursor.com>
propertyFetch of IS_STATIC/IS_METHOD on free closures reads uninitialized
slots and segfaults thin AOT; set those flags from Variable metadata only.

Co-authored-by: Cursor <cursoragent@cursor.com>
@PurHur
PurHur merged commit 7da0802 into master Aug 3, 2026
1 check failed
@PurHur
PurHur deleted the agent/issue-27219-aot-closure-bindto branch August 3, 2026 09:46
PurHur added a commit that referenced this pull request Aug 3, 2026
…27224) (#27230)

* Trust: refresh gen-0 argv fingerprint after #27221 (Pillar 1) (#27224)

Honest make bootstrap-gen0-refresh-argv-driver after Closure::bindTo
lowering drift; stamp verified-fresh fingerprint b60f971b… and sync
inventory construct flags so north-star5-fast step 4f-m clears.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Trust: restamp gen-0 argv after #27225 rebase (#27224)

Re-run honest argv refresh so fingerprint matches tip live sources
(9bbac6a0…) after call_user_func TypeError landed on master.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: PurHur <PurHur@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
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.

Regression: AOT Closure::bindTo() aborts after build — VM/JIT match Zend (Zend/zend_closures.c)

1 participant