Bug #70965 [Csd->Ver]: `yield from` with a common iterator primes too much

From: Date: Tue, 24 Nov 2015 23:14:32 +0000
Subject: Bug #70965 [Csd->Ver]: `yield from` with a common iterator primes too much
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-197406@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=70965&edit=1

 ID:                 70965
 Updated by:         bwoebi@php.net
 Reported by:        srice at fb dot com
 Summary:            yield from with a common iterator primes too much
-Status:             Closed
+Status:             Verified
 Type:               Bug
 Package:            Scripting Engine problem
 Operating System:   Linux
 PHP Version:        7.0.0RC7
 Assigned To:        bwoebi
 Block user comment: N
 Private report:     N

 New Comment:

You are right… re-opening, will fix tomorrow…


Previous Comments:
------------------------------------------------------------------------
[2015-11-24 23:11:51] 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 22:55:54] 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 21:14:38] 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 20:56:05] requinix@php.net

Looks similar to bug #70904.

------------------------------------------------------------------------
[2015-11-24 17:35:25] 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


------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=70965&edit=1


Thread (7 messages)

« previous php.bugs (#197406) next »