Skip to content

[PFA 2/n] Support PFA functionality#20848

Open
arnaud-lb wants to merge 61 commits intophp:masterfrom
arnaud-lb:partials-v2-gen
Open

[PFA 2/n] Support PFA functionality#20848
arnaud-lb wants to merge 61 commits intophp:masterfrom
arnaud-lb:partials-v2-gen

Conversation

@arnaud-lb
Copy link
Copy Markdown
Member

@arnaud-lb arnaud-lb commented Jan 6, 2026

RFC: https://wiki.php.net/rfc/partial_function_application_v2

This follows #20717. This implements most of the RFC, except PFAs in constant expressions, and some optimization.

I wanted to split this PR more, but I didn't find a way to achieve this that makes sense.


A partial application is compiled to the usual sequence of function call
opcodes (INIT_FCALL, SEND_VAR, etc), but the sequence ends with a
CALLABLE_CONVERT_PARTIAL opcode instead of DO_FCALL, similarly to
first class callables. Placeholders are compiled to SEND_PLACEHOLDER opcodes:

$f = f($a, ?)
0001 INIT_FCALL f
0002 SEND_VAR CV($a)
0003 SEND_PLACEHOLDER
0004 CV($f) = CALLABLE_CONVERT_PARTIAL

SEND_PLACEHOLDER sets the argument slot type to _IS_PLACEHOLDER.

CALLABLE_CONVERT_PARTIAL uses the information available on the stack to
create a Closure and return it, consuming the stack frame in the process
like an internal function call.

We create the Closure by generating the relevant AST and compiling it to an
op_array.

The op_array is cached in the Opcache SHM and inline caches. The SHM key is prefixed with pfa:// to avoid any collision with actual files. When Opcache is disabled, we cache PFA op_arrays a global hash table. This is mainly useful for polymorphic PFAs, as the inline cache stores only a single entry.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants