Category
language / runtime
Problem
foreach ($obj as $k => $v) only supports arrays and generators today. Objects implementing Iterator, IteratorAggregate, or Traversable fatals on VM:
LogicException: Iterator reset requires an array
Zend walks objects via internal iterator handlers (zend_iterator_*).
php-src reference
Zend/zend_interfaces.c — zend_class_implements, Traversable / Iterator checks
Zend/zend_execute.c — ZEND_FE_RESET_R, ZEND_FE_FETCH_R, object iterator path
Zend/zend_iterators.c — zend_iterator_* helpers for user iterators
Repro (today)
<?php
class T implements Iterator {
private int $i = 0;
public function current(): mixed { return $this->i; }
public function key(): mixed { return $this->i; }
public function next(): void { $this->i++; }
public function rewind(): void { $this->i = 0; }
public function valid(): bool { return $this->i < 3; }
}
foreach (new T() as $k => $v) {
echo "$k:$v\n";
}
./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && php bin/vm.php repro.php'
Zend PHP: prints 0:0, 1:1, 2:2
This compiler: LogicException: Iterator reset requires an array at lib/VM.php:1126
Also cover IteratorAggregate (getIterator(): Traversable).
Scope (this repo)
| Layer |
Files |
Notes |
| Compiler |
lib/Compiler.php |
Emit object-foreach ops or reuse iterator opcodes with object dispatch |
| VM |
lib/VM.php |
TYPE_ITER_RESET / TYPE_ITER_VALID / TYPE_ITER_FETCH call $obj->rewind() / valid() / current() / key() / next() |
| JIT |
lib/JIT.php |
Phase 2 — VM fallback acceptable v1 |
| Tests |
test/compliance/cases/foreach_iterator.phpt, foreach_iterator_aggregate.phpt |
VM first |
Done when
Verification
./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && vendor/bin/phpunit --filter foreach_iterator'
Dependencies
Links
Category
language/runtimeProblem
foreach ($obj as $k => $v)only supports arrays and generators today. Objects implementingIterator,IteratorAggregate, orTraversablefatals on VM:Zend walks objects via internal iterator handlers (
zend_iterator_*).php-src reference
Zend/zend_interfaces.c—zend_class_implements,Traversable/IteratorchecksZend/zend_execute.c—ZEND_FE_RESET_R,ZEND_FE_FETCH_R, object iterator pathZend/zend_iterators.c—zend_iterator_*helpers for user iteratorsRepro (today)
./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && php bin/vm.php repro.php'Zend PHP: prints
0:0,1:1,2:2This compiler:
LogicException: Iterator reset requires an arrayatlib/VM.php:1126Also cover
IteratorAggregate(getIterator(): Traversable).Scope (this repo)
lib/Compiler.phplib/VM.phpTYPE_ITER_RESET/TYPE_ITER_VALID/TYPE_ITER_FETCHcall$obj->rewind()/valid()/current()/key()/next()lib/JIT.phptest/compliance/cases/foreach_iterator.phpt,foreach_iterator_aggregate.phptDone when
TypeError(or Zend-equivalent) — not LogicException./script/ci-fast.sh --filter foreach_iteratorgreendocs/capabilities-syntax.mddocuments object foreach (regenerate viascript/capability-syntax.php)Verification
./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && vendor/bin/phpunit --filter foreach_iterator'Dependencies
Iteratoruser classes with__get)Links