Re: [RFC] Partial Function Application v2

From: Date: Mon, 13 Oct 2025 17:00:50 +0000
Subject: Re: [RFC] Partial Function Application v2
References: 1 2 3 4 5  Groups: php.internals 
Request: Send a blank email to internals+get-128821@lists.php.net to get a copy of this message
Hi Tim, On Sun, Oct 12, 2025 at 8:36 PM Tim Düsterhus <tim@bastelstu.be> wrote: > Relatedly to the stack trace example and also to the “Evaluation order” > I'd be curious how pre-filled parameters are implemented technically. > For pre-filled variables, the regular variable capturing logic would > work, but it doesn't for function returns. Is it effectively creating a > temporary variable under the hood? Meaning is: > > $partial = speak(?, getArg()); > > desugared into: > > $pfa_tmp_2 = getArg(); > $partial = fn (string $who) => speak($who, $pfa_tmp2); > > ? Pre-filled parameters are passed to the Closure via used vars, but there is no requirement for them to be in a CV slot so we don't need to create a temporary variable. We can bind used vars to any zval directly. The code $partial = speak(?, getArg()); Is compiled to INIT_FCALL speak SEND_PLACEHOLDER INIT_FCALL getArg T1 = DO_FCALL SEND T1 CALLABLE_CONVERT_PARTIAL The CALLABLE_CONVERT_PARTIAL opcode generates the AST for function (string $who) use ($msg) { return \speak($who, $msg); }; and compiles it (this is cached in SHM). It then instantiates the Closure, and binds $msg to ZEND_CALL_ARG(2). A few other values are passed via used vars, such as the object if it's an instance method call, or the underlying function if it's a closure. > - How does it interact with > ReflectionFunctionAbstract::getClosureUsedVariables()? > - Same question for other scope introspection functionality (e.g. Xdebug).. getClosureUsedVariables() and other introspection functionality will report any used var as usual. Used vars are named after the parameter if there is no collision. But this should not be considered API as this may change. For instance, I want to optimize-out used vars for parameters that are pre-filled with a literal. It would be possible to hide used vars of a PFA in Reflection. Best Regards, Arnaud

« previous php.internals (#128821) next »