Category
language | stdlib · php-src-strict · regression vs closed #3114
Problem
BackedEnum::tryFrom() and BackedEnum::from() must resolve a backing scalar to the canonical enum case object (E::A). Audit (2026-06-19): both methods fail for valid backing values — tryFrom(1) returns NULL and from(1) throws ValueError: 1 is not a valid backing value even when E::A = 1 exists.
This blocks enum deserialization, HTTP/query parsing, and any code using tryFrom/from at runtime. Distinct from #9889 (invalid-value error message when lookup path runs).
php-src reference
Repro
test/repro-maintainer/backed_enum_from_tryfrom.php:
<?php
enum E: int { case A = 1; case B = 2; }
var_export(E::tryFrom(1));
echo "\n";
var_export(E::from(1));
echo "\n";
enum Color: string { case Red = 'red'; }
var_export(Color::tryFrom('red'));
echo "\n";
Commands
php test/repro-maintainer/backed_enum_from_tryfrom.php
# Zend:
# \E::A
# \E::A
# \Color::Red
./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && php bin/vm.php test/repro-maintainer/backed_enum_from_tryfrom.php'
# VM today:
# NULL
# ValueError: 1 is not a valid backing value for enum E
| Call |
Zend |
VM (today) |
E::tryFrom(1) |
\E::A |
NULL |
E::from(1) |
\E::A |
ValueError |
Color::tryFrom('red') |
\Color::Red |
NULL |
Scope (PHP-in-PHP)
| Path |
Work |
lib/VM/BackedEnum.php |
caseForValue() / matchCaseForBackingValue() — ensure ClassEntry::$enumCases populated at runtime |
lib/VM/EnumFromHandler.php |
execute() return path via BackedEnum::canonicalCaseVariable() |
lib/VM/EnumSupport.php |
Case table / constant fallback (#9603) |
| Tests |
test/compliance/cases/language/backed_enum_from_tryfrom.phpt |
No new C in runtime/ — lookup belongs in PHP VM helpers.
Done when (php-src-strict)
Related
Category
language|stdlib· php-src-strict · regression vs closed #3114Problem
BackedEnum::tryFrom()andBackedEnum::from()must resolve a backing scalar to the canonical enum case object (E::A). Audit (2026-06-19): both methods fail for valid backing values —tryFrom(1)returnsNULLandfrom(1)throwsValueError: 1 is not a valid backing valueeven whenE::A = 1exists.This blocks enum deserialization, HTTP/query parsing, and any code using
tryFrom/fromat runtime. Distinct from #9889 (invalid-value error message when lookup path runs).php-src reference
Zend/zend_enum.c—zend_try_enum_from_case(),zend_enum_from_case(), backed-value hashZend/zend_enum.stub.php—BackedEnum::from/tryFromRepro
test/repro-maintainer/backed_enum_from_tryfrom.php:Commands
E::tryFrom(1)\E::ANULLE::from(1)\E::AValueErrorColor::tryFrom('red')\Color::RedNULLScope (PHP-in-PHP)
lib/VM/BackedEnum.phpcaseForValue()/matchCaseForBackingValue()— ensureClassEntry::$enumCasespopulated at runtimelib/VM/EnumFromHandler.phpexecute()return path viaBackedEnum::canonicalCaseVariable()lib/VM/EnumSupport.phptest/compliance/cases/language/backed_enum_from_tryfrom.phptNo new C in
runtime/— lookup belongs in PHP VM helpers.Done when (php-src-strict)
tryFrom(invalid)returnsnull;from(invalid)throwsValueErrorwith php-src message (Language: BackedEnum::from() invalid value — ValueError not 'Method call on non-object' (Zend/zend_enum.c) #9889)get_debug_type(E::from(1)) === 'E'docs/capabilities.mdRelated
cases()) · Epic: Self-host critical path — compiler compiles itself (M3→M5) #1492