On Fri, Jul 17, 2026, at 6:28 AM, Rob Landers wrote:
> On Fri, Jul 17, 2026, at 12:41, Wendell Adriel wrote:
> Hi Wendell,
>
> Thanks for updating the RFC.
>
> My largest concern is that this proposal substantially overlaps with
> the reified generics RFC, which is being held until after the current
> code freeze in late August or early September at the earliest.
>
> In particular, both proposals need to answer many of the same questions
> around parameterized types, variance, Reflection, runtime enforcement,
> inference, and type identity. I think we should avoid committing PHP to
> a separate set of array-specific rules before the broader generics
> proposal has been discussed. Otherwise, we risk either constraining the
> generics design or ending up with two parameterization models that
> behave differently.
>
> My second concern is the proposed variance model. It is extremely
> complex for a mutable built-in collection. Collections are normally
> invariant unless their API clearly separates reading from writing. The
> generics RFC follows that model: generic parameters are invariant by
> default, and covariance or contravariance is permitted only where their
> usage can be proven safe.
>
> Here, an `array<Dog>` is treated as compatible with `array<Animal>`
> only at selected by-value boundaries, based on PHP's copy-on-write
> separation. It then becomes invariant for writable aliases and requires
> additional rules for shared references.
>
> That does not appear to establish a normal subtype relationship. It
> establishes context-dependent boundary compatibility whose soundness
> depends on engine-level array separation and reference behavior. I
> think that will be challenging for users to understand and difficult
> for the engine to enforce consistently.
>
> Making parameterized arrays invariant would be substantially simpler:
>
> array<int, Dog> !== array<int, Animal>
>
> If covariance is desirable, I think it should come from a separate
> read-only collection or interface rather than from mutable arrays.
>
> My third concern is the one-argument syntax:
>
> array<TValue>
>
> This implicitly means:
>
> array<int, TValue>
>
> That is surprising. It is not a general array of values because string
> keys are rejected, but it is not a list either because the integer keys
> need not be contiguous or zero-based. I would expect `array<TValue>` to
> constrain only the value type, with the key type remaining
> `int|string`. A future `list<TValue>` could express the more
> restrictive numeric-keyed form.
>
> Lastly, I am concerned about repeated runtime validation. Since
> ordinary arrays do not retain a trusted element-type identity, an
> untyped boundary loses any information established by an earlier check:
>
> function foo(array<Bar> $arr): int
> {
> $acc = 0;
>
> foreach ($arr as $bar) {
> $acc += $bar->count;
> }
>
> return $acc;
> }
>
> function bar(array $arr): int
> {
> return foo($arr);
> }
>
> $arr = get_super_huge_array();
> echo bar($arr);
>
> At the call to foo(), PHP must recursively validate the entire array
> again, even if the same array was previously checked elsewhere. For
> large or nested arrays, this makes a type declaration potentially
> introduce an O(n) or recursive O(n) cost at every typed boundary.
>
> This is another reason I think typed arrays should be considered
> together with the wider generics design. A broader design may be able
> to provide type identity, inference, specialized collection types, or
> another mechanism that avoids repeatedly rediscovering the element type
> by traversing the value.
>
> I would strongly prefer that this RFC wait until the reified generics
> RFC has been discussed, or at minimum limit itself to syntax and
> Reflection experimentation without committing to independent variance
> and runtime semantics.
>
> — Rob
I am opposed to this RFC, for all the reasons Rob mentioned. Moreover, I don't
believe the issues can be resolved by just waiting for the reified generics RFC
(which I really hope passes). The core issue is that PHP arrays are an
over-broad data structure, and we need to have a hard, type-based (not just
implied by generics) distinction between lists/sequences, sets, and
dictionaries/maps, the same way most languages do.
There are a few ways that could be done: 3 generic objects (a la Kotlin, my
preferred approach), 3 generic objects with extension functions (assuming we
can get those), 3 new core data types with extension functions (very hard to
implement as I understand it), etc.
But tacking it onto the already-dangerously-overloaded array mega-type is the
wrong approach.
--Larry Garfield