Re: [RFC Idea] Generic Collection Notation for Iterables (array<T>)

From: Date: Sat, 27 Dec 2025 21:06:20 +0000
Subject: Re: [RFC Idea] Generic Collection Notation for Iterables (array<T>)
References: 1  Groups: php.internals 
Request: Send a blank email to internals+get-129703@lists.php.net to get a copy of this message
Hi, On Sat 27. 12. 2025 at 16:28, Jordi Kroon <jordikroon@me.com> wrote: > Hi everyone, > > I would like to propose a new type in PHP: Generic Collection Notation > for Iterables (array<T>). > > **The problem** > PHP provides several ways to represent sequences of values: > > - array > - iterable > - Traversable implementations > - generators > > While these constructs are fundamental to PHP, none of them allow the > developer to express **what type of values they yield or contain** at > the language level. > > > This leads to several issues: > - Static analysis relies heavily on PHPDoc annotations. > - Runtime type hints communicate structure but not intent. > - APIs lack self descriptive type information. > - Developers must duplicate type information across signatures and > documentation. > > **Example** > ```php > class UserService > { > /** > * @return User[] > */ > public function getAllUsers(): array > { > return [new User("Alice"), new User("Bob")]; > } > > /** > * @param User $user > * @param Role[] $roles > * @return void > */ > public function saveRoles($user, array $roles): void > { > // Some database call > } > } > ``` > > **The proposal** > Introduce parameterized iterable types using generic like syntax: > array<T> > iterable<T> > Traversable<T> > Generator<T> > > ```php > function processUsers(array<User> $users): void { } > > function normalize(array<string> $values): array<string> { } > ``` > > Optionally we could also extend the new array syntax with this > functionality. > > ```php > function processUsers(User[] $users): void { } > > function normalize(string[] $values): string[] { } > ``` > > Key points: > - The existing array type remains valid and unchanged. > - array<T> means an array whose elements are of type > T. > - The syntax is currently invalid in PHP and therefore does not > introduce a backward compatibility break. > > **Example** > ```php > class UserService > { > public function getAllUsers(): array<User> > { > return [new User("Alice"), new User("Bob")]; > } > > public function saveRoles(User $user, array<Role> $roles): void > { > // Some database call > } > > public function streamAllUsers(): Generator<User> > { > yield new User("Alice"); > yield new User("Bob"); > } > > public function iterateAllUsers(): ArrayIterator<User> > { > return new ArrayIterator([new User("Alice"), new User("Bob")]); > } > > public function getUserProvider(): Traversable<User> > { > return new ArrayIterator([new User("Alice"), new User("Bob")]); > } > > public function normalizeNames(iterable<string> $names): > iterable<string> > { > foreach ($names as $name) { > yield trim($name); > } > } > } > ``` > > **Runtime semantics and enforcement** > The goal is that array<T> and related iterable > parameterizations > behave like other PHP types: if a value is passed or returned that > violates the declared type, a TypeError is thrown. > > The main question is when and how enforcement occurs for eager versus > lazy containers. > - Checked on function argument receive, property assignment, and return. > - Each element value is validated against T. > There are two approaches, but only one gives strong runtime guarantees. > > Preferred behavior: > - Validate on consumption when the iterable is iterated. > - If a yielded element violates T, throw > TypeError at the point > of iteration. > > This mirrors the fact that iterable may be lazy and cannot be > fully > validated up front. > > **Implementation** > I have basic C knowledge but I don't have much experience with Zend > Engine / PHP Core. However I am fully committed to: > - Write and maintain the RFC document. > - Test and write tests for the implementation or draft > - Participate in discussions > - Collaborate with anyone willing to help with the implementation > > **Keys and additional parameters** > This proposal focuses on element types. Keys are intentionally out of > scope for the initial version. > > Possible follow up work could explore array<TKey, > TValue> and > Generator<TKey, TValue>. > > **Next steps** > - I would like to have hear any potential caveats. For example > regarding lazy loading. > - If the RFC gains internal support, I will officially publish the > first initial draft of the RFC. > - Whether supporting the shorthand T[] should be part of the > initial > scope or a follow up > - Whether supporting TKey should be part of the initial scope > or a > follow up This has been discussed in past and we actually talked about it internally quite recently. IMHO only T[] should be supported to not give partial generics and disallow nested arrays. Arnaud described best the possible issues in https://externals.io/message/125049#125069 . There is really not much point to do RFC without implementation so you will probably need to find someone who is willing and capable to implement it. Kind regards, Jakub >

« previous php.internals (#129703) next »