Skip to content

Language: BackedEnum::from() / tryFrom() (#3114) - #3152

Merged
PurHur merged 10 commits into
masterfrom
agent/issue-3114-enum-from
May 31, 2026
Merged

Language: BackedEnum::from() / tryFrom() (#3114)#3152
PurHur merged 10 commits into
masterfrom
agent/issue-3114-enum-from

Conversation

@PurHur

@PurHur PurHur commented May 29, 2026

Copy link
Copy Markdown
Owner

Summary

VM lowering for backed enum ::from() and ::tryFrom() with case lookup by backing value (Zend zend_enum.c parity).

php-src reference

  • Zend/zend_enum.czend_enum_from_case(), zend_try_enum_from_case()
  • Zend/zend_interfaces.cBackedEnum internal API

Verification

# Issue repro
./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && php bin/vm.php -r '"'"'enum Color: string { case Red = "red"; case Blue = "blue"; } echo Color::from("red")->name; echo Color::tryFrom("nope") === null ? "null" : "bad";'"'"''
# Rednull

./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && vendor/bin/phpunit test/unit/VmEnumFromTest.php test/compliance/EnumVMTest.php --filter "VmEnumFrom|enum_from|enum_try_from"'
# OK (8 tests)

./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && vendor/bin/phpunit test/unit/VmEnumBasicTest.php test/compliance/EnumVMTest.php --filter enum_basic'
# OK — no regression

Note: enum_instanceof.phpt failure is pre-existing on master (#3550), unrelated to this PR. JIT deferred per issue scope.

Closes #3114

@PurHur

PurHur commented May 29, 2026

Copy link
Copy Markdown
Owner Author

Maintainer local verify (Docker docker-exec, master base + PR branch)

vendor/bin/phpunit --filter VmEnumFromTest on PR head errors (0 assertions):

TypeError: PHPCfg\Op\Stmt\Enum_::__construct(): Argument #3 ($implements) must be of type array, PHPCfg\Block given

Looks like php-cfg Parser enum path vs Enum_ ctor mismatch in the container’s vendor tree — please confirm composer install + patches on the branch and that unit tests pass with:

./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && vendor/bin/phpunit --filter VmEnumFromTest'

Not merging until green; VM compliance enum_from phpt path is the issue repro from the PR body.

PurHur and others added 10 commits May 31, 2026 08:41
Implement zend_enum_from_case-style lookup for backed enums, enum case
values with name/value properties, and clear callArgEntries after internal
handlers so chained static calls receive the correct arguments.

Co-authored-by: Cursor <cursoragent@cursor.com>
Internal handlers route ValueError through executeInternalHandler →
raiseUncaughtException (Exception), matching other runtime builtins until
native ValueError propagation lands (#195).

Co-authored-by: Cursor <cursoragent@cursor.com>
Guards int backing type lookup alongside existing string enum_from/try_from
cases. php-src: Zend/zend_enum.c zend_enum_from_case().

Co-authored-by: Cursor <cursoragent@cursor.com>
Match php-src zend_enum.c message format (enum name unquoted) and add
enum_from_invalid.phpt plus caught ValueError unit coverage.

php-src: Zend/zend_enum.c — zend_enum_from_case()
Co-authored-by: Cursor <cursoragent@cursor.com>
Normalize int-backed numeric strings and scalar coercions before case
lookup so Level::from('1') matches Zend; reject non-numeric strings with
TypeError. Adds unit coverage for int string acceptance and bad input.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Run enum overlay chain before typed-class-const so Op\Stmt\Enum_ receives
int $flags before attributes. Tighten abstract-patch skip detection and
guard with ApplyPatchesTest.

Co-authored-by: Cursor <cursoragent@cursor.com>
apply_php_cfg_enum_class_method_parser_fix() is invoked without an
argument from apply_php_cfg_enum_early_chain(); default to vendor
Parser.php like sibling helpers to avoid set -u unbound $1 abort.

Co-authored-by: Cursor <cursoragent@cursor.com>
apply_php_cfg_enum_overlay copies the flags-bearing Enum_.php overlay
then may return early without updating Parser.php, leaving vendor in a
state where Op\Stmt\Enum_ expects int $flags but parseStmt_Enum passes
attributes as argument #5. Add php_cfg_sync_enum_flags_parser() and
invoke it from enum overlay paths and the early chain.

Co-authored-by: Cursor <cursoragent@cursor.com>
Map materialized VM Throwable objects to native PHP exceptions in
raiseUncaughtException so BackedEnum::from() invalid values throw
ValueError (not generic Exception) per Zend parity.

php-src: Zend/zend_enum.c — zend_enum_from_case()
Co-authored-by: Cursor <cursoragent@cursor.com>
@PurHur
PurHur force-pushed the agent/issue-3114-enum-from branch from 7bd4739 to 54fb12e Compare May 31, 2026 08:41
@PurHur
PurHur merged commit 129e055 into master May 31, 2026
@PurHur
PurHur deleted the agent/issue-3114-enum-from branch May 31, 2026 08:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Language: enum_from() — BackedEnum::from / tryFrom (PHP 8.1)

1 participant