-
-
Notifications
You must be signed in to change notification settings - Fork 929
Description
Bug report
I'm attempting to implement a class that has caching for the method's return values.
For example, given a class Cat
that has three methods:
count_descendants(): int
is_hungry(): bool
get_name(): string
I have a private $result_cache
class member variable which is typed as follows:
* @phpstan-type ResultCache array{
* count_descendants?: int<1, max>,
* is_hungry?: bool,
* name?: non-empty-string
* }
There is a get_cached_result
method which is used as follows:
public function count_descendants(): int {
return $this->get_cached_result( __FUNCTION__, static function () {
return 123; // TODO: Some expensive operation.
} );
}
And finally the get_cached_result
method itself is implemented as follows:
/**
* Get cached result.
*
* @template K of key-of<ResultCache>
* @phpstan-param K $method Method.
* @phpstan-param Closure(): ResultCache[K] $callback Callback.
* @phpstan-return ResultCache[K]
*
* @param string $method Method name.
* @param Closure $callback Callback to get the result.
* @return mixed
*/
private function get_cached_result( string $method, Closure $callback ) {
if ( array_key_exists( $method, $this->result_cache ) ) {
return $this->result_cache[ $method ];
}
$result = $callback();
$this->result_cache[ $method ] = $result;
return $result;
}
The problem is on this line:
$this->result_cache[ $method ] = $result;
PHPStan is flagging this as an error saying that $result
is:
array{
count_descendants?: bool|int<1, max>|non-empty-string,
is_hungry?: bool|int<1, max>|non-empty-string,
name?: bool|int<1, max>|non-empty-string
}
Which does not match the type of $result_cache
which is (as shown above):
array{
count_descendants?: int<1, max>,
is_hungry?: bool,
name?: non-empty-string
}
What seems to be happening is PHPStan thinks the type of $result
is a union of all possible types for the array values in the ResultCache
type. But this seems like it should not be because I specified that the supplied closure returns the type ResultCache[K]
where K
is one of key-of<ResultCache>
.
Is this a bug in PHPStan? Or am I just doing generics wrong?
Code snippet that reproduces the problem
https://phpstan.org/r/b203ec8c-2d70-469c-b24f-9e7143cff72d
Expected output
I believe this is a false positive. No error should have been detected.
Did PHPStan help you today? Did it make you happy in any way?
No response