Skip to content

feat(variance)!: adopt Kotlin-style out/in variance markers#22

Merged
math3usmartins merged 3 commits into
0.3.xfrom
feat/kotlin-variance-markers
Jul 6, 2026
Merged

feat(variance)!: adopt Kotlin-style out/in variance markers#22
math3usmartins merged 3 commits into
0.3.xfrom
feat/kotlin-variance-markers

Conversation

@math3usmartins

Copy link
Copy Markdown
Member

Summary

Replaces the Scala/Hack-style declaration-site variance markers +T (covariant) /
-T (contravariant) with the Kotlin/C#-style out T / in T, aligning xphp's
surface syntax with the spelling chosen for PHP's generics. This is a hard swap:
+T / -T are no longer accepted.

// before
class Producer<+T> { /* … */ }
class Consumer<-T> { /* … */ }

// after
class Producer<out T> { /* … */ }
class Consumer<in T> { /* … */ }

Variance semantics are unchanged — the subtyping lift, position validation, edge
emission, and registry are identical. Only the surface spelling and the diagnostic
wording move; emitted PHP is byte-for-byte the same.

Details

  • Contextual keywords. out / in act as a marker only when immediately followed
    by the parameter name (out T, never outT). Ordinary parameters whose names merely
    start with those letters (outer, input, outT) are unaffected.
  • Reserved names. out / in cannot themselves name a type parameter, so
    class Box<out>, class Box<out out>, and class Pair<in, out> fail with a single
    clear diagnostic.
  • Migration error. Old +T / -T source now raises an explicit error pointing at
    the new spelling instead of an opaque downstream parse failure.
  • Diagnostics (xphp.variance_position, unprovable-edge warnings, inner-variance
    composition) now render out T / in T to match what the user wrote.
  • Method/function/closure/arrow variance stays rejected (unchanged, message updated).

math3usmartins and others added 3 commits July 6, 2026 00:24
Replace the Scala/Hack variance markers `+T` (covariant) / `-T`
(contravariant) with `out T` / `in T`, matching the syntax selected for
PHP's generics. `out`/`in` are contextual keywords: a plain identifier
acts as a marker only when immediately followed by the parameter name
(`out T`, never `outT`), so names that merely start with `out`/`in`
stay ordinary parameters.

`out` and `in` are reserved as markers and cannot name a type parameter
(checked at the name slot, so `class Box<out>`, `class Box<out out>`,
and `class Pair<in, out>` all fail with one clear diagnostic). The old
`+T` / `-T` glyphs now raise an explicit migration error instead of an
opaque downstream parse failure. Variance semantics, the `Variance`
enum, and every downstream soundness pass are unchanged; only the
surface spelling moves. Fixtures and parser tests migrated accordingly.

BREAKING CHANGE: `+T` / `-T` variance syntax is no longer accepted;
write `out T` / `in T`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The variance-position, unprovable-edge, and inner-variance diagnostics
built their parameter display from the enum with the old `+`/`-` sigil,
so a program written with `out T` / `in T` would be told its error is on
`+T`. Render the marker as `out`/`in` to match the source syntax.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Update the syntax reference, comparison guide, ADRs, caveats, error
catalogue, and changelog for the `out T` / `in T` spelling. Also correct
the error catalogue's "verbatim" method-variance message (it had drifted
to a paraphrase and said "not yet supported" for what is a permanent,
by-design boundary) and fix the article agreement in the variance-position
entry. Released changelog history is left as written.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@math3usmartins math3usmartins merged commit 4a371db into 0.3.x Jul 6, 2026
6 checks passed
@math3usmartins math3usmartins deleted the feat/kotlin-variance-markers branch July 6, 2026 01:31
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