Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong returntype "never" for generator function with endless loop #10638

Open
UlrichEckhardt opened this issue Feb 2, 2024 · 3 comments
Open

Comments

@UlrichEckhardt
Copy link
Contributor

Heya!

Check out this example code, in particular the complaint about the return value of the events() function. This function is actually a generator running in an endless loop, the only way out is with an exception. It seems that this combination (endless loop and exception) confuses Psalm enough to flag this as an error. If I just remove the check $events === false and the exception, the complaint about the return value goes away. It still complains about other things then, but those are actual flaws in the code or that Psalm online doesn't recognize the IN_* constants.

I have honestly no idea how to fix this, so I'm relying on your help here.

Regards

Uli

Copy link

I found these snippets:

https://psalm.dev/r/b2075861de
<?php

declare(strict_types=1);

/**
 * @param resource $inotify 
 * @return Generator<array>
 */
function events($inotify): Generator
{
    while (true) {
        $events = inotify_read($inotify);
        if ($events === false) {
            throw new Exception('inotify_read() failed');
        }
        foreach ($events as $event) {
            yield $event;
        }
    }
}

$inotify = inotify_init();
inotify_add_watch($inotify, __DIR__, IN_ALL_EVENTS);
foreach (events($inotify) as $event) {
    echo json_encode($event, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . PHP_EOL;
}
Psalm output (using commit bf57d59):

INFO: MixedAssignment - 16:29 - Unable to determine the type that $event is being assigned to

ERROR: InvalidReturnType - 7:12 - The declared return type 'Generator<mixed, array<array-key, mixed>, mixed, mixed>' for events is incorrect, got 'never'

ERROR: UndefinedConstant - 23:38 - Const IN_ALL_EVENTS is not defined

INFO: MixedArgument - 23:38 - Argument 3 of inotify_add_watch cannot be mixed, expecting int

ERROR: UnusedFunctionCall - 23:1 - The call to inotify_add_watch is not used

UlrichEckhardt added a commit to UlrichEckhardt/simplequeue that referenced this issue Feb 2, 2024
Both flaws are rather caused by Psalm than the code:

- One complaint ("int does not contain false") about the return value
  of `inotify_add_watch()` is a bug in Psalm, resulting from one in the
  PHP docs, which only list `int` as possible return type. It can
  return `false` though (vimeo/psalm#10636).
- The other complaint ("The declared return type 'Generator<...>' for
  InotifyWatch::getIterator is incorrect, got 'never'") looks like a
  bug, too. It seems to think that the function never returns, which is
  kind-of true, but it does yield values which makes `Generator` the
  correct type (vimeo/psalm#10638).
@weirdan
Copy link
Collaborator

weirdan commented Feb 3, 2024

Simplified: https://psalm.dev/r/a6fea04924

Copy link

I found these snippets:

https://psalm.dev/r/a6fea04924
<?php

declare(strict_types=1);

/**
 * @return Generator<int>
 */
function ints(): Generator
{
    while (true) {
        if (rand(0, 1)) {
            throw new Exception;
        }
        yield 1;
    }
}

foreach (ints() as $int) {
    echo $int;
}
Psalm output (using commit bf57d59):

ERROR: InvalidReturnType - 6:12 - The declared return type 'Generator<mixed, int, mixed, mixed>' for ints is incorrect, got 'never'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants