Description
The following code:
<?php
class A {
public static function name(): string {
return (static fn () => static::class)();
}
}
class B extends A {}
class C extends A {}
var_dump(B::name(), C::name());
Resulted in this output:
string(1) "B"
string(1) "B"
But I expected this output instead:
string(1) "B"
string(1) "C"
8.4 and 8.5 give the expected output. 8.6.0RC2 does not, with or without opcache.
Bisected to f47cd21 (#23203). Its parent 969a50d gives "B", "C". Still reproduces on PHP-8.6 7f56584 and master 69ca307.
Cc @iluuu1994
Written with LLM assistance, per CONTRIBUTING.md. The code, outputs and bisect above are measured.
It also happens in inherited instance methods, and with new static() and get_called_class(). A non-static closure is fine. We hit it in bensampo/laravel-enum, where the second enum class gets instances of the first.
Unverified guess: ZEND_DECLARE_LAMBDA_FUNCTION returns the cached closure without checking the called scope, and all subclasses share the slot in the declaring op_array.
PHP Version
PHP 8.6.0RC2 (cli) (built: Sep 24 2026 20:13:06) (NTS clang 15.0.0)
Copyright © The PHP Group and Contributors
Built by Laravel Herd
Zend Engine v4.6.0RC2, Copyright © Zend by Perforce
with Zend OPcache v8.6.0RC2, Copyright ©, by Zend by Perforce
Operating System
macOS 26.6.2 (arm64)
Description
The following code:
Resulted in this output:
But I expected this output instead:
8.4 and 8.5 give the expected output. 8.6.0RC2 does not, with or without opcache.
Bisected to f47cd21 (#23203). Its parent 969a50d gives
"B","C". Still reproduces on PHP-8.6 7f56584 and master 69ca307.Cc @iluuu1994
PHP Version
Operating System
macOS 26.6.2 (arm64)