TypePHP 编译器
https://swoole.com/aot/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
112 lines
2.4 KiB
112 lines
2.4 KiB
--TEST--
|
|
foreach invokes only required Iterator callbacks and cleans up exceptional cursors
|
|
--FILE--
|
|
<?php
|
|
|
|
class CallbackIterator implements Iterator
|
|
{
|
|
public static int $keyCalls = 0;
|
|
private int $position = 0;
|
|
|
|
public function __construct(private string $failure = '')
|
|
{
|
|
}
|
|
|
|
public function rewind(): void
|
|
{
|
|
if ($this->failure === 'rewind') throw new RuntimeException('rewind');
|
|
$this->position = 0;
|
|
}
|
|
|
|
public function valid(): bool
|
|
{
|
|
if ($this->failure === 'valid') throw new RuntimeException('valid');
|
|
return $this->position < 2;
|
|
}
|
|
|
|
public function current(): mixed
|
|
{
|
|
if ($this->failure === 'current') throw new RuntimeException('current');
|
|
return $this->position + 10;
|
|
}
|
|
|
|
public function key(): mixed
|
|
{
|
|
++self::$keyCalls;
|
|
if ($this->failure === 'key') throw new RuntimeException('key');
|
|
return $this->position;
|
|
}
|
|
|
|
public function next(): void
|
|
{
|
|
if ($this->failure === 'next') throw new RuntimeException('next');
|
|
++$this->position;
|
|
}
|
|
}
|
|
|
|
final class LifetimeIterator extends CallbackIterator
|
|
{
|
|
public static int $destroyed = 0;
|
|
public function __destruct()
|
|
{
|
|
++self::$destroyed;
|
|
}
|
|
}
|
|
|
|
final class LifetimeAggregate implements IteratorAggregate
|
|
{
|
|
public function getIterator(): Traversable
|
|
{
|
|
return new LifetimeIterator();
|
|
}
|
|
}
|
|
|
|
function consume(string $failure, bool $withKey): void
|
|
{
|
|
try {
|
|
if ($withKey) {
|
|
foreach (new CallbackIterator($failure) as $key => $value) {
|
|
}
|
|
} else {
|
|
foreach (new CallbackIterator($failure) as $value) {
|
|
}
|
|
}
|
|
} catch (RuntimeException $exception) {
|
|
echo $exception->getMessage(), "\n";
|
|
}
|
|
}
|
|
|
|
function main(): void
|
|
{
|
|
foreach (new CallbackIterator() as $value) {
|
|
echo $value, "\n";
|
|
}
|
|
var_dump(CallbackIterator::$keyCalls);
|
|
|
|
foreach (new CallbackIterator() as $key => $value) {
|
|
}
|
|
var_dump(CallbackIterator::$keyCalls);
|
|
|
|
consume('rewind', false);
|
|
consume('valid', false);
|
|
consume('current', false);
|
|
consume('next', false);
|
|
consume('key', true);
|
|
|
|
foreach (new LifetimeAggregate() as $value) {
|
|
break;
|
|
}
|
|
var_dump(LifetimeIterator::$destroyed);
|
|
}
|
|
?>
|
|
--EXPECT--
|
|
10
|
|
11
|
|
int(0)
|
|
int(2)
|
|
rewind
|
|
valid
|
|
current
|
|
next
|
|
key
|
|
int(1)
|
|
|