Hi Tim, We will update the RFC, but here are a few answers:
On Wednesday, July 2nd, 2025 at 17:05, Tim Düsterhus <t...@bastelstu.be> wrote: > I've now had a quick look at the implementation and the following > questions came up that the RFC does not answer (and the tests in the PR > do not obviously answer either): > > How will PFA calls appear in a stack trace and how will PFA Closures > look like to `var_dump()`, Reflection, and to observers? PFAs are instances of the Closure class (like FCCs), and will look like a Closure to `var_dump()`, Reflection, and observers. The Closure signature reflects the parameters that are accepted by the PFA, not the underlying function (so it exposes only unbound parameters). function f(int $a, int $b) { } $f = f(?, 2); echo new ReflectionFunction($f); // Output: Partial [ <user> function f ] { @@ test.php 5 - 5 - Parameters [1] { Parameter #0 [ <required> int $a ] } } PFA Reflection is tested in Zend/tests/partial_application/reflection_*.phpt. Parameter names, and which parameters are required, are defined by the RFC. Currently, a few things are broken in the implementation, including parameter default value reflection. Additionally, `var_dump()` exposes bound and unbound args (with the value of bound args). Currently the `var_dump()` output looks like this: object(Closure)#1 (5) { ["name"]=> string(1) "f" ["file"]=> string(%d) "test.php" ["line"]=> int(7) ["parameter"]=> array(1) { ["$a"]=> string(10) "<required>" } ["args"]=> array(2) { ["a"]=> NULL ["b"]=> int(2) } } PFAs do not appear in stack traces, only the function does. > Classic FCC are 100% identical to the underlying function and thus can > just “pretend” they are the underlying function, but that doesn't work > for PFA. Consider the following: > > function foo(string $s, int $i) { > var_dump($s, $i); > } > > $f = foo("abc", ?); > > $f([]); > > How will the error message for the resulting TypeError look like? Error messages refer to the underlying function as if it was called directly: Uncaught TypeError: foo(): Argument #2 ($i) must be of type int, array given, in test.php on line 7 The line number refers to the call site of the PFA ($f([])), not its instantiation. However, since PFAs must check argument count before binding them, errors related to argument count refer to the PFA itself. Currently the error message for $f() looks like this: Uncaught Error: not enough arguments for application of foo, 0 given and exactly 1 expected, declared in test.php on line 5 in test.php on line 7 > var_dump((new ReflectionFunction($f))->getName()); The underlying function name (like FCCs) > var_dump((new ReflectionFunction($f))->getParameters()); See above > is_callable($f, callable_name: $name); > var_dump($name); Closure::__invoke (like FCCs) > function foo(string $s, #[\SensitiveParameter] int $i) { > throw new \Exception(); > } > > $f = foo("abc", ?); > > $f(123); > > How will the stack trace look like? Does `#[\\SensitiveParameter]` work > properly? This is broken, but the intent is to support attributes, so that SensitiveParameter and other attributes work as expected. Best Regards, Arnaud