-
Notifications
You must be signed in to change notification settings - Fork 686
Description
Psalm incorrectly triggers an InvalidReturnStatement
when a generator function, with a declared return type of iterable
, uses a return statement with a value. It appears Psalm attempts to validate this return value against the iterable<K, V>
, rather than treating it as the generator's R
type.
If such a function has a declared return type like iterable<K, V>
or iterable<V>
, its actual signature is closer to Generator<K, V, S = mixed, R = mixed>
.
The return $value;
statement within a generator sets the R
type parameter. This value is distinct from the iterable
.
Currently, Psalm seems to incorrectly assume that $value
in return $value;
must conform to iterable<K, V>
.
The following code demonstrates the issue:
<?php
/**
* @param array<string, string> $array
* @return iterable<string>
*/
function generator(array $array): iterable
{
yield $array['key'] ?? 'default';
return 1; // this is an error, because `1` does not match `iterable<string>`
}
/**
* @param array<string, string> $array
* @return iterable<string>
*/
function generator2(array $array): iterable
{
yield $array['key'] ?? 'default';
return []; // this is fine because `[]` matches `iterable<string>`
}
Suggested Resolution:
When analyzing a generator function with an iterable
return type:
- Recognize that
return $value;
defines theR
type of the underlyingGenerator
. - do not validate
$value
against theiterable<K, V>
- If the
R
type needs to be statically checked, Psalm could perhaps assumeR
is mixed when onlyiterable
is specified, or require the more explicitGenerator
type hint if theR
type is important to the user.
The current behavior is misleading because the value from return in a generator is not meant to be an instance of the iterable
type itself, but rather the result obtained from Generator::getReturn()
.