Bug #65598 [Com]: Closure executed via static autoload incorrectly marked as static

From: Date: Fri, 08 May 2015 09:11:52 +0000
Subject: Bug #65598 [Com]: Closure executed via static autoload incorrectly marked as static
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-192577@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=65598&edit=1

 ID:                 65598
 Comment by:         arjen at react dot com
 Reported by:        php at davidstockton dot com
 Summary:            Closure executed via static autoload incorrectly
                     marked as static
 Status:             Closed
 Type:               Bug
 Package:            Scripting Engine problem
 Operating System:   Centos 6
 PHP Version:        5.5.3
 Assigned To:        nikic
 Block user comment: N
 Private report:     N

 New Comment:

I'm not sure about the following behaviour: 

<?php

class A {
    public static function exec(callable $c)
    {
	// this works
	$c();

	// this won't
        return call_user_func($c);
    }
    
    public static function doSomething()
    {
	// implicit static in 5.x, non-static in 7
        return self::exec(function(){
            return "okay";
        });
    }
}

echo A::doSomething();


After this commit, the closure created by doSomething and passed to exec() cannot be called by
call_user_func anymore: "Fatal error: Non-static method A::{closure}() cannot be called
statically in staticClosures.php on line 10"

However, calling $c(); still works.

Is this expected or an unwanted effect of this patch?


Previous Comments:
------------------------------------------------------------------------
[2015-05-06 16:19:21] nikic@php.net

Fixed in PHP 7 by https://github.com/php/php-src/commit/bc2ff4a299a182c4ab9681fa6ba52cf747f53ace.
This won't be backported, as it depends on some other changes, which are ABI incompatible.

------------------------------------------------------------------------
[2013-09-20 16:10:24] php at davidstockton dot com

Your examples make sense. However in this particular case, it seems to make sense 
that the autoloader's "staticness" would or should not affect the things that are 
loaded via the autoloader-i.e, make a special case for autoloaders.

The behavior of the code should not be changed based on whether the code was 
loaded via a static or non-static autoloader.

------------------------------------------------------------------------
[2013-09-18 06:52:29] bixuehujin at gmail dot com

Indeed,it is odd and out of expect.

AFAIK, there is no difference between create closure in static methods and require a file that will
create a closure. Because of the created closure in both have the same scope.
 
Consider the following two examples:

1: create closure in static method

//main.php

class Test {
    public static function createClosure() {
        $c = function () {
            //some code
        };
        return $c;
    }
}

2: create closure in a single file and require it

//main.php

class Test {
    public static function createClosure() {
        require 'closure.php';
        return $c;
    }
}

//closure.php
$c = function () {
    //some code
};

The both examples have the same behavior, and both scope of $c are Test. 

But according to the invariants in Zend/zend_closures.c, say:

> If the closure is unscoped, it has no bound object.
> The the closure is scoped, it's either static or it's bound 
> see detail: https://github.com/php/php-src/blob/47ee470992014c738891d05b5acc89c2de90f2ac/Zend/zend_closures.c#L483,L498

So the behavior of this issue is valid according to the invariants.


*By the way, i am also want to know why we should have the invariants.*

------------------------------------------------------------------------
[2013-09-17 21:30:38] php at davidstockton dot com

The closure is not created in a static method, it's just loaded via an autoloader 
that happens to be static. Seems odd that we should expect different behavior of the 
code based on if the autoloader is static or non-static.

------------------------------------------------------------------------
[2013-09-17 20:52:18] bixuehujin at gmail dot com

The reason is closures created in static methods are static, even without the keyword.

see https://github.com/php/php-src/blob/a447acdcc6f12ea3a5dcd22416cb033e62995935/Zend/tests/closure_045.phpt

------------------------------------------------------------------------


The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at

    https://bugs.php.net/bug.php?id=65598


--
Edit this bug report at https://bugs.php.net/bug.php?id=65598&edit=1


Thread (10 messages)

« previous php.bugs (#192577) next »