Skip to content

ReflectionMethod::invokeArgs() for Closure::__invoke() accepts objects from different Closures #21362

Description

@TimWolla

Description

The following code:

<?php

$c = function ($foo, $bar) {
	echo "foo: {$foo}, bar: {$bar}\n";
};

$m = new ReflectionMethod($c, '__invoke');

$firstParam = $m->getParameters()[0]->getName();
var_dump($firstParam);
$secondParam = $m->getParameters()[1]->getName();
var_dump($secondParam);

$args = [
    $firstParam => 'FOO',
    $secondParam => 'BAR',
];

$m->invokeArgs(function ($bar, $foo) {
	echo "foo: {$foo}, bar: {$bar}\n";
}, $args);

Resulted in this output:

string(3) "foo"
string(3) "bar"
foo: BAR, bar: FOO

But I expected this output instead:

string(3) "foo"
string(3) "bar"
Fatal error: Uncaught ReflectionException: Given object is not an instance of the class this method was declared in

Semantically closures are behave if they were different, incompatible, classes that extend a Closure base class and the __invoke() method is defined on the closure-specific class rather than the base class. The observable signature differs for each Closure definition. This is also becoming obvious by new ReflectionMethod('Closure', '__invoke') failing when only the classname rather than an object is being provided:

Fatal error: Uncaught ReflectionException: Method Closure::__invoke() does not exist in php-src/test6.php:7
Stack trace:
#0 php-src/test6.php(7): ReflectionMethod->__construct('Closure', '__invoke')
#1 {main}
  thrown in php-src/test6.php on line 7

PHP Version

git master @ f99ca6347f456e18adb22c8c89e92681bb55d84d

Operating System

No response

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions