php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #70965 `yield from` with a common iterator primes too much
Submitted: 2015-11-24 17:35 UTC Modified: 2015-11-24 23:14 UTC
From: srice at fb dot com Assigned: bwoebi (profile)
Status: Closed Package: Scripting Engine problem
PHP Version: 7.0.0RC7 OS: Linux
Private report: No CVE-ID: None
 [2015-11-24 17:35 UTC] srice at fb dot com
Description:
------------
When two separate generator instances `yield from` a common iterator the second element of the iterator gets skipped. There is a test case to keep this from happening with a common shared generator (and the fix keeps track of which generator is priming or not) but it doesnt work with iterators. See the sample script below (which is mostly just a small change to the `multiple_yield_from_on_same_generator` test that already exists).

Test script:
---------------
<?php

function it() {
    yield from [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
}

function bar($g) {
    yield from $g;
}

$gen = it();
$gens[] = bar($gen);
$gens[] = bar($gen);

do {
    foreach($gens as $g) {
        var_dump($g->current());
        $gen->next();
    }
} while ($gen->valid());

Expected result:
----------------
int(1)
int(2)
int(3)
int(4)
int(5)
int(6)
int(7)
int(8)
int(9)
int(10)

Actual result:
--------------
int(1)
int(3)
int(4)
int(5)
int(6)
int(7)
int(8)
int(9)
int(10)
NULL

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-11-24 20:56 UTC] requinix@php.net
Looks similar to bug #70904.
 [2015-11-24 21:14 UTC] srice at fb dot com
I used a similar test case for both of them, but I actually worked around the linked bug in this test case (notice the `while` statement is checking the inner generator for validity, while the linked bug checks the outer generator for validity).

This one seems to be due to autopriming (autopriming the second generator advances the shared iterator) while the other is due to the valid method returning the result of valid on the delegate generator (which is not an assumption you can make, since the outer generator still might have yields to execute).
 [2015-11-24 22:55 UTC] bwoebi@php.net
-Status: Open +Status: Closed -Assigned To: +Assigned To: bwoebi
 [2015-11-24 22:55 UTC] bwoebi@php.net
Just seen this now… I've just fixed this "accidentally" as a side effect by the bugfix for #70904 :-)

The last two values should be int(10) int(10); this is the case because the validity of the calling generator is not affected by the validity of the yielded generator. The values are just synchronized between all generators. So the last value of the generators is actually the last value of the subgenerator you yielded from. (which is why it's twice.)
 [2015-11-24 23:11 UTC] srice at fb dot com
Thanks for the quick response! To be clear, the issue isnt the null at the end, its that `int(2)` never gets yielded. An element is skipped in the iterator.

I'll let you decide to reopen the bug or not (cause I'm not sure if its still fixed by your other change), but I'm pretty sure the last two values shouldn't be `int(10)` `int(10)`.
 [2015-11-24 23:14 UTC] bwoebi@php.net
-Status: Closed +Status: Verified
 [2015-11-24 23:14 UTC] bwoebi@php.net
You are right… re-opening, will fix tomorrow…
 [2015-11-25 08:55 UTC] bwoebi@php.net
Automatic comment on behalf of bobwei9@hotmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=73a92964ffd80ae907314b8202ed99716e4ba918
Log: Fixed bug #70965 (yield from with a common iterator primes too much)
 [2015-11-25 08:55 UTC] bwoebi@php.net
-Status: Verified +Status: Closed
 [2015-11-25 08:56 UTC] bwoebi@php.net
Automatic comment on behalf of bobwei9@hotmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=73a92964ffd80ae907314b8202ed99716e4ba918
Log: Fixed bug #70965 (yield from with a common iterator primes too much)
 [2016-07-20 11:35 UTC] davey@php.net
Automatic comment on behalf of bobwei9@hotmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=73a92964ffd80ae907314b8202ed99716e4ba918
Log: Fixed bug #70965 (yield from with a common iterator primes too much)
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 14:01:29 2024 UTC