Skip to content

feat: covariant self-returns, use-const/enum-name parse edges, exception $previous, unknown-array foreach keys#473

Open
chadmandoo wants to merge 1 commit into
illegalstudio:mainfrom
chadmandoo:upstream-pr/conformance-and-parse-completeness
Open

feat: covariant self-returns, use-const/enum-name parse edges, exception $previous, unknown-array foreach keys#473
chadmandoo wants to merge 1 commit into
illegalstudio:mainfrom
chadmandoo:upstream-pr/conformance-and-parse-completeness

Conversation

@chadmandoo

Copy link
Copy Markdown
Contributor

Five bounded completeness fixes found compiling real strict-typed PHP:

  • INTERFACE COVARIANCE: an implementation may return a narrower type than the interface declares (the PSR-7 withX(): static shape). type_accepts can never see it — the class under validation is not yet registered mid-construction — so conformance accepts a self-typed return from its own context: the validated interface (or one it extends), or any interface the class declares (or one those extend).
  • PARSE: use const PHP_INT_MAX; — the lexer eagerly tokenizes such constants; the use-declaration prefix accepts the dedicated tokens by canonical spelling (imports are inert — expression uses lower to literals). class Enum / new Enum / Vendor\Enumenum is a soft keyword (vendor precedent: marc-mabe/php-enum); parse_name and the class-decl name accept it.
  • EXCEPTIONS: builtin exception constructors accept PHP's third $previous parameter (positional or named). Not stored — the compact throwable payload has no previous slot and getPrevious() is already synthesized as null — wrap-and-rethrow code compiles with byte-identical message/code round-trips.
  • FOREACH KEYS: iterating an unknown-element array (array-hinted param/property) types keys as Mixed, not Int — the value may be associative at runtime.

Byte-parity vs PHP 8.5 on all five regression tests.

chadmandoo added a commit to chadmandoo/elephc that referenced this pull request Jul 10, 2026
….1 (R6/#595)

Three v0.26.0 enum/parser fixes, survey-driven (79% → 85%, 241 → 262/307):

- ENUM-CASE PARAM DEFAULT (illegalstudio#468, declarations.rs): `E $x = E::Case` — an
  enum-case default has the enum object type, but syntactic inference types
  every `::` access as Str. When the declared type is Object(E) and the
  default is a scoped access naming E, accept it (the semantic pass validates
  the case exists). Clears the Badge/Button `$variant expects Object, got Str`
  family (9).
- KEYWORD ENUM-CASE NAMES (body.rs): PHP 8 allows semi-reserved keywords as
  enum-case names (`case Default;`, `case String;`, `case Float;`) — every one
  but `class` (reserved for `Foo::class`). Clears CardVariant/LogicalType/
  HeadAssetMode `Expected case name after 'case'` (10).
- USE CONST/FUNCTION IMPORTS (illegalstudio#473/EC-10/illegalstudio#493, namespace_use.rs): the lexer
  eagerly tokenizes `PHP_INT_MAX` etc., so the use-declaration parser must
  accept those dedicated tokens as import names (`use const PHP_INT_MAX;`).
  Clears RegionEntry `Expected imported name after 'use'` (2).

Deferred (not survey-visible on v0.26.1): illegalstudio#469 keyword-case access, illegalstudio#472 clone.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…es, exception $previous, unknown-array foreach keys

Four bounded completeness fixes:

- Interface covariant self-returns: an implementation may return a NARROWER
  type than the interface declares (`withX(): static` against an
  interface-typed return, the PSR-7 wither shape). The class under
  validation is mid-construction when conformance runs, so the covariance is
  proven from the conformance context itself.
- Parse edges: `use const PHP_INT_MAX;` (the lexer eagerly tokenizes such
  constants, so the use-declaration parser must accept the dedicated tokens
  as import names) and a class/enum declared with a keyword-spelled name.
- Exception `$previous`: the builtin Exception/Error constructor accepts its
  third `?Throwable $previous` argument.
- foreach KEYS over an unknown-element array (an `array`-hinted param whose
  elements are known only to phpdoc) type as Mixed, not Int — the value may
  be associative at runtime (a header-map shape with string keys).

Byte-parity vs PHP 8.5 on all regression tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@chadmandoo
chadmandoo force-pushed the upstream-pr/conformance-and-parse-completeness branch from cce7e0f to ea5b326 Compare July 11, 2026 14:13
@github-actions github-actions Bot added area:codegen Touches target-aware assembly or backend lowering. area:parser Touches parsing or AST construction. area:types Touches type checking, inference, or compatibility. size:m Medium-sized pull request. type:feature Introduces new user-visible behavior or capabilities. labels Jul 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:codegen Touches target-aware assembly or backend lowering. area:parser Touches parsing or AST construction. area:types Touches type checking, inference, or compatibility. size:m Medium-sized pull request. type:feature Introduces new user-visible behavior or capabilities.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant