Skip to content

Stdlib: IteratorIterator / RegexIterator — SPL iterator adapters missing (ext/spl/spl_iterators.c) #6138

Closed

Description

@PurHur

Category

stdlib

Problem

Zend registers IteratorIterator (wrap any Traversable as Iterator) and RegexIterator (filter iterator elements by PCRE). These are among the most-used SPL adapters — e.g. new IteratorIterator($generator) and new RegexIterator($it, '/^foo/'). This compiler has partial SPL skeletons (#3330, #4769) but neither class exists (class_exists → false, Jun 2026 parity audit).

#4546 tracks LimitIterator/FilterIterator/etc.; this issue covers the adapter pair specifically because they unblock foreach over foreign iterators and regex-filtered walks.

php-src reference

  • ext/spl/spl_iterators.c — spl_ce_RegexIterator, spl_ce_IteratorIterator
  • ext/spl/spl_iterators.stub.php — RegexIterator::MATCH, GET_MATCH, USE_KEY, …
  • Zend/zend_interfaces.c — Iterator / Traversable checks

Repro A — IteratorIterator

<?php
function gen(): Generator { yield 'a'; yield 'b'; }
$it = new IteratorIterator(gen());
foreach ($it as $v) { echo $v; }
echo "\n";

Repro B — RegexIterator

<?php
$base = new ArrayIterator(['foo', 'bar', 'food']);
$it = new RegexIterator($base, '/^foo/', RegexIterator::MATCH);
foreach ($it as $v) { echo $v, "\n"; }
./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && php bin/vm.php repro_a.php && php bin/vm.php repro_b.php'
php repro_a.php && php repro_b.php
Runtime Repro A Repro B
Zend PHP 8.x ab + newline foo + newline
bin/vm.php fatal: IteratorIterator not found fatal: RegexIterator not found

Scope (this repo)

Area Path Notes
ext/spl new class handlers Real iterator protocol — no permanent stubs
VM reuse lib/VM.php foreach / VmIteratorWalk.php IteratorIterator delegates to inner iterator
PCRE ext/standard/VmPreg.php RegexIterator uses existing preg engine
Tests test/compliance/cases/stdlib/spl_iterator_iterator.phpt, spl_regex_iterator.phpt
Matrix script/capability-matrix.php

v1 RegexIterator modes: MATCH only. Defer: REPLACE, SPLIT, GET_MATCH.

Done when

  • Repro A prints ab on VM
  • Repro B prints foo on VM
  • RegexIterator constants (MATCH, USE_KEY, …) defined
  • Non-iterator ctor operand → TypeError per Zend
  • ./script/ci-fast.sh --filter 'IteratorIterator|RegexIterator' green

Verification

./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && vendor/bin/phpunit --filter IteratorIterator'

Links

Activity

  1. added
    enhancementNew feature or request
    phase-4:stdlibPhase 4 – stdlib for web apps
    area:vmVirtual machine
    implementation-readySpec complete: repro, php-src ref, done-when — safe for workers to claim
    on Jun 5, 2026
  2. PurHur commented on Jul 15, 2026

    @PurHur
    OwnerAuthor

    claim: PHP Compiler STD Lib Advanced — batch (issues #4387, #6138, #6563)

    Queued after #4387. IteratorIterator works for ArrayIterator; Generator inner yields LogicException on rewind (Expected Generator instance).

  3. PurHur commented on Jul 15, 2026

    @PurHur
    OwnerAuthor

    claim: PHP Compiler STD Lib Advanced — implementing first (ahead of #4387)

    Root cause: SplDualIteratorStorage (and sibling wrappers) keep bare ObjectEntry pointers without ObjectLifetime::addRef. A temporary gen() dies when the construct arg slot is released; destroyForGc() clears generatorState, so later rewind()/valid() throw Expected Generator instance. Named $g = gen() stays alive via the user Variable ref.

    Fix: pin inner iterators on store (same pattern as RecursiveCallbackFilterIteratorBuiltin::copyVar).

  4. PurHur commented on Jul 15, 2026

    @PurHur
    OwnerAuthor

    Merged via PR #19327.

    Root cause: Outer wrappers stored bare ObjectEntry for gen() temps; frame teardown destroyed the Generator (generatorState cleared) before foreach rewind().

    Fix: Pin Variable roots + preserve/reattach GeneratorState in SplIteratorSupport before callInner.

    Verification:

    php bin/vm.php test/repro/issue_6138_iteratoriterator_temp_generator.php
    # ok ×3
    php -d memory_limit=1536M vendor/bin/phpunit --filter iteratoriterator_temp_generator
    # OK (2 tests)
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:vmVirtual machineenhancementNew feature or requestimplementation-readySpec complete: repro, php-src ref, done-when — safe for workers to claimphase-4:stdlibPhase 4 – stdlib for web apps

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions