Category
stdlib · language
Problem
Zend registers internal interfaces (UnitEnum, BackedEnum, ArrayAccess, Serializable, …) in the class table. interface_exists() and get_declared_interfaces() must return them even though user code never declared them.
This compiler only scans user-declared interfaces in VmReflection::interfaceExists() / declaredInterfacesTable() (ext/standard/VmReflection.php). Builtin interfaces are missing:
| Check |
Zend PHP 8.2+ |
bin/vm.php today |
interface_exists('UnitEnum') |
true |
false |
interface_exists('BackedEnum') |
true |
false |
interface_exists('ArrayAccess') |
true |
false |
interface_exists('Serializable') |
true |
false |
in_array('UnitEnum', get_declared_interfaces(), true) |
true |
false |
is_a($enumCase, UnitEnum::class) |
true |
fatal: Unknown class for constant fetch: UnitEnum |
instanceof on enum cases for builtin interfaces was fixed in #5711 (closed), but reflection builtins and UnitEnum::class constant fetch still fail — blocking generic enum utilities and self-host code that introspects enums.
php-src reference
Repro
Save as test/repro/parity_builtin_interface_registry.php:
<?php
enum E: string { case A = 'a'; }
$c = E::A;
foreach (['UnitEnum', 'BackedEnum', 'ArrayAccess', 'Serializable'] as $iface) {
echo "interface_exists($iface): ", var_export(interface_exists($iface), true), "\n";
}
echo "declared UnitEnum: ", var_export(in_array('UnitEnum', get_declared_interfaces(), true), true), "\n";
echo "is_a case UnitEnum: ";
try {
var_export(is_a($c, UnitEnum::class));
} catch (Throwable $e) {
echo get_class($e), ': ', $e->getMessage();
}
echo "\n";
./script/docker-exec.sh -- bash -lc 'source script/php-env.sh
php test/repro/parity_builtin_interface_registry.php
php bin/vm.php test/repro/parity_builtin_interface_registry.php 2>&1 | grep -v listSpreadRhs
'
Scope (this repo)
| Area |
Path |
| Registry |
lib/VM/BuiltinInterfaces.php (new) — seed internal ClassEntry rows at VM init |
| Enum parity |
lib/VM/EnumSupport.php — ensure enum cases satisfy instanceof builtin interfaces (regression guard for #5711) |
| Stdlib |
ext/standard/VmReflection.php — interfaceExists(), declaredInterfacesTable() include builtins |
| Constant fetch |
lib/VM.php / class table — resolve UnitEnum::class, BackedEnum::class for is_a() / is_subclass_of() |
| JIT |
ext/standard/JitInterfaceExists.php, lib/JIT/ReflectionBuiltinHelper.php — literal builtin interface names |
| Tests |
test/compliance/cases/stdlib/builtin_interface_exists.phpt, test/compliance/cases/language/enum_is_a_unit_enum.phpt |
PHP-in-PHP: register builtins in PHP (lib/VM/), not new C tables in runtime/.
Done when
Verification
./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && vendor/bin/phpunit --filter builtin_interface'
Links
Category
stdlib·languageProblem
Zend registers internal interfaces (
UnitEnum,BackedEnum,ArrayAccess,Serializable, …) in the class table.interface_exists()andget_declared_interfaces()must return them even though user code never declared them.This compiler only scans user-declared interfaces in
VmReflection::interfaceExists()/declaredInterfacesTable()(ext/standard/VmReflection.php). Builtin interfaces are missing:bin/vm.phptodayinterface_exists('UnitEnum')truefalseinterface_exists('BackedEnum')truefalseinterface_exists('ArrayAccess')truefalseinterface_exists('Serializable')truefalsein_array('UnitEnum', get_declared_interfaces(), true)truefalseis_a($enumCase, UnitEnum::class)trueUnknown class for constant fetch: UnitEnuminstanceofon enum cases for builtin interfaces was fixed in #5711 (closed), but reflection builtins andUnitEnum::classconstant fetch still fail — blocking generic enum utilities and self-host code that introspects enums.php-src reference
Zend/zend_interfaces.c—zend_register_internal_interface,UnitEnum,BackedEnum,ArrayAccess,Serializableext/standard/basic_functions.c—PHP_FUNCTION(interface_exists),get_declared_interfacesext/standard/class.c—is_a(),is_subclass_of()with internal interfacesZend/zend_enum.c— enum caseinstanceofbuiltin interfacesRepro
Save as
test/repro/parity_builtin_interface_registry.php:Scope (this repo)
lib/VM/BuiltinInterfaces.php(new) — seed internalClassEntryrows at VM initlib/VM/EnumSupport.php— ensure enum cases satisfyinstanceofbuiltin interfaces (regression guard for #5711)ext/standard/VmReflection.php—interfaceExists(),declaredInterfacesTable()include builtinslib/VM.php/ class table — resolveUnitEnum::class,BackedEnum::classforis_a()/is_subclass_of()ext/standard/JitInterfaceExists.php,lib/JIT/ReflectionBuiltinHelper.php— literal builtin interface namestest/compliance/cases/stdlib/builtin_interface_exists.phpt,test/compliance/cases/language/enum_is_a_unit_enum.phptPHP-in-PHP: register builtins in PHP (
lib/VM/), not new C tables inruntime/.Done when
interface_exists()lines printtrueon VMget_declared_interfaces()includesUnitEnumandBackedEnumis_a(E::A, UnitEnum::class)printstrue(no constant-fetch fatal)./script/ci-fast.sh --filter builtin_interfacegreenclass_implements/is_subclass_ofbehavior on user enums)Verification
./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && vendor/bin/phpunit --filter builtin_interface'Links