Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:129698 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: by lists.php.net (Postfix, from userid 65534) id 7EC311A00BD; Sat, 27 Dec 2025 15:26:33 +0000 (UTC) To: internals@lists.php.net Date: Sat, 27 Dec 2025 16:26:32 +0100 Precedence: list list-help: list-unsubscribe: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Content-Language: en-GB Subject: [PHP-DEV] [RFC Idea] Generic Collection Notation for Iterables (array) Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Posted-By: 86.92.4.88 Message-ID: <20251227152633.7EC311A00BD@lists.php.net> From: jordikroon@me.com (Jordi Kroon) Hi everyone, I would like to propose a new type in PHP: Generic Collection Notation for Iterables (`array`). **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` `iterable` `Traversable` `Generator` ```php function processUsers(array $users): void { } function normalize(array $values): array { } ``` 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` 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 { return [new User("Alice"), new User("Bob")]; } public function saveRoles(User $user, array $roles): void { // Some database call } public function streamAllUsers(): Generator { yield new User("Alice"); yield new User("Bob"); } public function iterateAllUsers(): ArrayIterator { return new ArrayIterator([new User("Alice"), new User("Bob")]); } public function getUserProvider(): Traversable { return new ArrayIterator([new User("Alice"), new User("Bob")]); } public function normalizeNames(iterable $names): iterable { foreach ($names as $name) { yield trim($name); } } } ``` **Runtime semantics and enforcement** The goal is that `array` 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` and `Generator`. **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