-
Notifications
You must be signed in to change notification settings - Fork 683
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 theRtype of the underlyingGenerator. - do not validate
$valueagainst theiterable<K, V> - If the
Rtype needs to be statically checked, Psalm could perhaps assumeRis mixed when onlyiterableis specified, or require the more explicitGeneratortype hint if theRtype 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().