psalm
psalm copied to clipboard
Wrong returntype "never" for generator function with endless loop
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
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
Simplified: https://psalm.dev/r/a6fea04924
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'