Bug #69586 [Opn->Nab]: Resolution of static function variables not using forwarded calling information

From: 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

« previous php.bugs (#232235) next »