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

From: Date: Sat, 27 Dec 2025 15:46:58 +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-129699@lists.php.net to get a copy of this message
On 27/12/2025 4:26 pm, Jordi Kroon 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**
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>
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.
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**
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 Kind regards, Jordi Kroon Yes, I am fully aware https://wiki.php.net/rfc/generic-arrays exists. But since it's older date I was not sure if I had to revive the original or start a new. That said since PHP is becoming a more strict language, it became more relevant. And the original RFC doesn't mention anything regarding Traversables or other iterables. Though I would like to give my sincere for the work that has been done for the current RFC proposal.


« previous php.internals (#129699) next »