Bug #69586 [Opn->Nab]: Resolution of static function variables not using forwarded calling information
| From: | nikic@php.net | Date: | Thu, 18 Feb 2021 10:49:31 +0000 |
| Subject: | Bug #69586 [Opn->Nab]: Resolution of static function variables not using forwarded calling information | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-232235@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=69586&edit=1
ID: 69586
Updated by: nikic@php.net
Reported by: php at lvl dot fastmail dot com
Summary: Resolution of static function variables not using
forwarded calling information
-Status: Open
+Status: Not a bug
Type: Bug
Package: Scripting Engine problem
PHP Version: 5.6.8
Block user comment: N
Private report: N
New Comment:
Static variables are bound to a specific method on a specific class, and have no relation to or
interaction with late static binding, nor should they.
Thus you end up caching whatever LSB scope you happen to use when you first call Animal::describe().
From this we may conclude that caching an LSB-dependent value in a static variable is ill-advised.
Previous Comments:
------------------------------------------------------------------------
[2015-05-06 15:05:19] php at lvl dot fastmail dot com
Description:
------------
I ran into some very strange behavior while experimenting with static function variables. Static
variables in the function scope appear to be resolved using late static binding: the content of the
variable in that function is shared amongst all instances of a class, though each subclass gets its
own separate variable space.
This is pretty logical and works fine. As an example, let's create classes Base => Animal
=> {Cat,Dog}. Base has a function that describes the class, and caches the result in a static
function variable $description. Calling describe() on the three different classes correctly gives us
three different results: http://3v4l.org/Qldve
However, once you override the describe function in Animal and call parent::describe() from within,
it looks like all calling information is lost: the resolution of $description in Base's
function scope now always points to Animal's variable space. For example: http://3v4l.org/CcrL8
I would have expected the static function variable and get_called_class() to always refer to the
same class/variable space, parent:: or not.
Overriding the function in one of the childmost classes like Dog gives an even stranger result:
$description is now correctly a separate value in Cat vs Dog, but calling Animal::describe() now
uses the value left by its child class Cat?! See: http://3v4l.org/61P72
Test script:
---------------
class Base {
public static function describe() {
echo "--> " . ($calculated = "I am a " . get_called_class() .
"\n");
static $cached = null;
if ($cached === null) {
$cached = $calculated;
}
return $cached;
}
}
class Animal extends Base {
public static function describe() {
return 'Hello! ' . parent::describe();
}
}
class Cat extends Animal { }
class Dog extends Animal { }
echo Cat::describe();
echo Dog::describe();
echo Animal::describe();
Expected result:
----------------
--> I am a Cat
Hello! I am a Cat
--> I am a Dog
Hello! I am a Dog
--> I am a Animal
Hello! I am a Animal
Actual result:
--------------
--> I am a Cat
Hello! I am a Cat
--> I am a Dog
Hello! I am a Cat
--> I am a Animal
Hello! I am a Cat
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=69586&edit=1