Re: [PHP-DEV] [RFC] Typed array declarations
[email protected] (MichaĆ Marcin Brzuchalski) Tue, 21 Jul 2026 16:59:34 +0200
| Newsgroups | php.internals |
|---|---|
| Message-ID | <CABdc3WqyuzYQxrf1X9tObf9FP6uHgLtuuDhaUWPf_gXYbFX1fw@mail.gmail.com> |
--000000000000fe3cca0657204545
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
pon., 20 lip 2026, 17:22 u=C5=BCytkownik Larry Garfield <larry@garfieldtech=
.com>
napisa=C5=82:
> 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> !=3D=3D 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 =3D 0;
> >
> > foreach ($arr as $bar) {
> > $acc +=3D $bar->count;
> > }
> >
> > return $acc;
> > }
> >
> > function bar(array $arr): int
> > {
> > return foo($arr);
> > }
> >
> > $arr =3D 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.
> >
> > =E2=80=94 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 functio=
ns
> (very hard to implement as I understand it), etc.
>
I suspect the 3rd option implementation challenge may not be as prohibitive
as it first appears. The design space seems larger than just "extend
arrays" versus "generic objects". I'm still exploring it though, so I'd
rather not jump to conclusions yet.
Cheers,
Micha=C5=82 Marcin Brzuchalski
>
--000000000000fe3cca0657204545
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"auto"><div><br><br><div class=3D"gmail_quote gmail_quote_contai=
ner"><div dir=3D"ltr" class=3D"gmail_attr">pon., 20 lip 2026, 17:22 u=C5=BC=
ytkownik Larry Garfield <<a href=3D"mailto:[email protected]">larry=
@garfieldtech.com</a>> napisa=C5=82:<br></div><blockquote class=3D"gmail=
_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204=
,204);padding-left:1ex">On Fri, Jul 17, 2026, at 6:28 AM, Rob Landers wrote=
:<br>
> On Fri, Jul 17, 2026, at 12:41, Wendell Adriel wrote:<br>
<br>
> Hi Wendell,<br>
><br>
> Thanks for updating the RFC.<br>
><br>
> My largest concern is that this proposal substantially overlaps with <=
br>
> the reified generics RFC, which is being held until after the current =
<br>
> code freeze in late August or early September at the earliest.<br>
><br>
> In particular, both proposals need to answer many of the same question=
s <br>
> around parameterized types, variance, Reflection, runtime enforcement,=
<br>
> inference, and type identity. I think we should avoid committing PHP t=
o <br>
> a separate set of array-specific rules before the broader generics <br=
>
> proposal has been discussed. Otherwise, we risk either constraining th=
e <br>
> generics design or ending up with two parameterization models that <br=
>
> behave differently.<br>
><br>
> My second concern is the proposed variance model. It is extremely <br>
> complex for a mutable built-in collection. Collections are normally <b=
r>
> invariant unless their API clearly separates reading from writing. The=
<br>
> generics RFC follows that model: generic parameters are invariant by <=
br>
> default, and covariance or contravariance is permitted only where thei=
r <br>
> usage can be proven safe.<br>
><br>
> Here, an `array<Dog>` is treated as compatible with `array<An=
imal>` <br>
> only at selected by-value boundaries, based on PHP's copy-on-write=
<br>
> separation. It then becomes invariant for writable aliases and require=
s <br>
> additional rules for shared references.<br>
><br>
> That does not appear to establish a normal subtype relationship. It <b=
r>
> establishes context-dependent boundary compatibility whose soundness <=
br>
> depends on engine-level array separation and reference behavior. I <br=
>
> think that will be challenging for users to understand and difficult <=
br>
> for the engine to enforce consistently.<br>
><br>
> Making parameterized arrays invariant would be substantially simpler:<=
br>
><br>
> array<int, Dog> !=3D=3D array<int, Animal><br>
><br>
> If covariance is desirable, I think it should come from a separate <br=
>
> read-only collection or interface rather than from mutable arrays.<br>
><br>
> My third concern is the one-argument syntax:<br>
><br>
> array<TValue><br>
><br>
> This implicitly means:<br>
><br>
> array<int, TValue><br>
><br>
> That is surprising. It is not a general array of values because string=
<br>
> keys are rejected, but it is not a list either because the integer key=
s <br>
> need not be contiguous or zero-based. I would expect `array<TValue&=
gt;` to <br>
> constrain only the value type, with the key type remaining <br>
> `int|string`. A future `list<TValue>` could express the more <br=
>
> restrictive numeric-keyed form.<br>
><br>
> Lastly, I am concerned about repeated runtime validation. Since <br>
> ordinary arrays do not retain a trusted element-type identity, an <br>
> untyped boundary loses any information established by an earlier check=
:<br>
><br>
> function foo(array<Bar> $arr): int<br>
> {<br>
>=C2=A0 =C2=A0 =C2=A0$acc =3D 0;<br>
><br>
>=C2=A0 =C2=A0 =C2=A0foreach ($arr as $bar) {<br>
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0$acc +=3D $bar->count;<br>
>=C2=A0 =C2=A0 =C2=A0}<br>
><br>
>=C2=A0 =C2=A0 =C2=A0return $acc;<br>
> }<br>
><br>
> function bar(array $arr): int<br>
> {<br>
>=C2=A0 =C2=A0 =C2=A0return foo($arr);<br>
> }<br>
><br>
> $arr =3D get_super_huge_array();<br>
> echo bar($arr);<br>
><br>
> At the call to foo(), PHP must recursively validate the entire array <=
br>
> again, even if the same array was previously checked elsewhere. For <b=
r>
> large or nested arrays, this makes a type declaration potentially <br>
> introduce an O(n) or recursive O(n) cost at every typed boundary.<br>
><br>
> This is another reason I think typed arrays should be considered <br>
> together with the wider generics design. A broader design may be able =
<br>
> to provide type identity, inference, specialized collection types, or =
<br>
> another mechanism that avoids repeatedly rediscovering the element typ=
e <br>
> by traversing the value.<br>
><br>
> I would strongly prefer that this RFC wait until the reified generics =
<br>
> RFC has been discussed, or at minimum limit itself to syntax and <br>
> Reflection experimentation without committing to independent variance =
<br>
> and runtime semantics.<br>
><br>
> =E2=80=94 Rob<br>
<br>
I am opposed to this RFC, for all the reasons Rob mentioned.=C2=A0 Moreover=
, I don't believe the issues can be resolved by just waiting for the re=
ified generics RFC (which I really hope passes).=C2=A0 The core issue is th=
at 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/sequen=
ces, sets, and dictionaries/maps, the same way most languages do.<br>
<br>
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 har=
d to implement as I understand it), etc.=C2=A0<br></blockquote></div></div>=
<div dir=3D"auto"><br></div><div dir=3D"auto">I suspect the 3rd option impl=
ementation challenge may not be as prohibitive as it first appears. The des=
ign space seems larger than just "extend arrays" versus "gen=
eric objects". I'm still exploring it though, so I'd rather no=
t jump to conclusions yet.</div><div dir=3D"auto"><br></div><div dir=3D"aut=
o">Cheers,</div><div dir=3D"auto">Micha=C5=82 Marcin Brzuchalski=C2=A0</div=
><div dir=3D"auto"><div class=3D"gmail_quote gmail_quote_container"><blockq=
uote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1p=
x solid rgb(204,204,204);padding-left:1ex">
</blockquote></div></div></div>
--000000000000fe3cca0657204545--