php / php/php-src

Inconsistent behaviour with AppendIterator and empty generators

未关闭
#11,591 7 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

Bug Category: Generators Extension: spl Status: Verified
主要语言
C
星标
40.4k
派生
8.1k
平均合并
2 天 13 小时
30 天内合并 PR
96

描述

Description

I've encountered inconsistent behaviour in the handling of empty generators with AppendIterator. Please can you confirm whether this is a bug or some weird expected behaviour.

Scenario 1

When iterating over a generator that yields nothing, foreach has no items to iterate over so var_dump isn't called, as expected.

<?php

function yieldEmpty()
{
    yield from [];
}

foreach (yieldEmpty() as $item) {
    var_dump($item);
}

Scenario 2

When attaching a generator yielding items and a generator yielding nothing and attaching both to an AppendIterator, foreach iterates over the items from the former and the three values are output, as expected.

<?php

function yieldRows()
{
    yield from ['one', 'two', 'three'];
}

function yieldEmpty()
{
    yield from [];
}

$iterator = new AppendIterator();
$iterator->append(yieldRows());
$iterator->append(yieldEmpty());

foreach ($iterator as $item) {
    var_dump($item);
}

Outputs (as expected):

string(3) "one"
string(3) "two"
string(5) "three"

Scenario 3

When attaching ONLY a generator yielding nothing and attaching it to an AppendIterator, foreach unexpectedly fails with an exception.

<?php

function yieldEmpty()
{
    yield from [];
}

$iterator = new AppendIterator();
$iterator->append(yieldEmpty());

foreach ($iterator as $item) {
    var_dump($item);
}

Expected output (following on from scenario 1 and 2):

string(3) "one"
string(3) "two"
string(5) "three"

Actual output:

PHP Fatal error:  Uncaught Exception: Cannot traverse an already closed generator in /Users/richard.coupland/test3.php:11
Stack trace:
#0 /Users/richard.coupland/test3.php(11): AppendIterator->rewind()
#1 {main}
  thrown in /Users/richard.coupland/test3.php on line 11

Fatal error: Uncaught Exception: Cannot traverse an already closed generator in /Users/richard.coupland/test3.php:11
Stack trace:
#0 /Users/richard.coupland/test3.php(11): AppendIterator->rewind()
#1 {main}
  thrown in /Users/richard.coupland/test3.php on line 11
PHP Version

8.2.7

Operating System

No response

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

首先,在 PHP 8.2.7 上使用 yieldEmpty 和 yieldRows 生成器重现三个 AppendIterator 场景,重点关注 foreach 和 AppendIterator->rewind() 期间的失败。确定这种不同行为是有意为之还是一个 bug,然后添加或更新回归测试覆盖,以便空生成器案例具有明确且通过测试的行为。

由索引模型根据 Issue 内容生成。

评估

技术栈
php
领域
backend
Issue 类型
缺陷
难度
3/5
预计耗时
1-2 天
活跃度
活跃
描述清晰度
基本清楚
新手友好度
55/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。