php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #79511 Return is silently ignored with yield even if yield is never reached
Submitted: 2020-04-23 00:38 UTC Modified: 2020-04-23 09:24 UTC
From: michael dot vorisek at email dot cz Assigned: cmb (profile)
Status: Not a bug Package: Scripting Engine problem
PHP Version: 7.4.5 OS: any
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: michael dot vorisek at email dot cz
New email:
PHP Version: OS:

 

 [2020-04-23 00:38 UTC] michael dot vorisek at email dot cz
Description:
------------
See test script

Test script:
---------------
function x(): iterable {
    yield 'a';
    
    return ['b']; // silently ignored!
}

function y(): iterable {
    if (false) {
        yield 'c';
    }
    
    return ['d']; // not returned at all - yield above needs to be commented out even if the condition is never matched!
}


foreach (x() as $v) {echo $v."\n";}
echo "\n";
foreach (y() as $v) {echo $v."\n";}

Expected result:
----------------
a
b

d

Actual result:
--------------
a



Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2020-04-23 07:16 UTC] cmb@php.net
-Status: Open +Status: Not a bug -Assigned To: +Assigned To: cmb
 [2020-04-23 07:16 UTC] cmb@php.net
No, the `return` is not ignored; it just has special semantics in
generator functions; see <https://3v4l.org/rCAX4> and
<https://github.com/php/php-langspec/blob/master/spec/14-classes.md#class-generator>.
 [2020-04-23 08:20 UTC] michael dot vorisek at email dot cz
But the 2nd example does not call yield at all - if (false) {} pattern is used a lot to comment code to keep it refactorable - why is this allowed and where is this behaviour defined?
 [2020-04-23 08:25 UTC] nikic@php.net
Any function containing yield is a generator and follows generator semantics. Whether the yield actually gets executed does not matter.

Please, this is generators 101.
 [2020-04-23 08:41 UTC] michael dot vorisek at email dot cz
This should then be - like return - not allowed, shouldn't?

$u = fn() => yield 5;
echo $u();
 [2020-04-23 08:50 UTC] nikic@php.net
Why would that be disallowed? It's equivalent to

function() {
    return yield 5;
}

which is not terribly useful, but perfectly legal code. It yields one value, accepts one value and specifies the accepted value as the coroutine return value.
 [2020-04-23 09:12 UTC] michael dot vorisek at email dot cz
Ok, just example how to mix non-generator and generator return.

class Cl {
    public function __get($name) {
        if ($name === 'gen') {
            return (fn() => yield 'a')(); // return generator
        } else {
            return ['b']; // return array
        }
    }
}

$cl = new Cl();
var_dump($cl->gen);
var_dump(iterator_to_array($cl->gen));
var_dump($cl->not_gen);
 [2020-04-23 09:24 UTC] cmb@php.net
In this case, Cl::__get() is a normal function, not a generator
function.  The anonymous function inside of Cl::__get() is a
generator function, though.
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Sun Nov 16 12:00:01 2025 UTC