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
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.

1 participant