4444 * }
4545 * ```
4646 *
47- * @param PromiseInterface $promise
48- * @return mixed returns whatever the promise resolves to
47+ * @template T
48+ * @param PromiseInterface<T> $promise
49+ * @return T returns whatever the promise resolves to
4950 * @throws \Exception when the promise is rejected with an `Exception`
5051 * @throws \Throwable when the promise is rejected with a `Throwable`
5152 * @throws \UnexpectedValueException when the promise is rejected with an unexpected value (Promise API v1 or v2 only)
@@ -93,13 +94,14 @@ function ($error) use (&$exception, &$rejected, &$wait, &$loopStarted) {
9394 // promise is rejected with an unexpected value (Promise API v1 or v2 only)
9495 if (!$ exception instanceof \Throwable) {
9596 $ exception = new \UnexpectedValueException (
96- 'Promise rejected with unexpected value of type ' . (is_object ($ exception ) ? get_class ($ exception ) : gettype ($ exception ))
97+ 'Promise rejected with unexpected value of type ' . (is_object ($ exception ) ? get_class ($ exception ) : gettype ($ exception )) // @phpstan-ignore-line
9798 );
9899 }
99100
100101 throw $ exception ;
101102 }
102103
104+ /** @var T $resolved */
103105 return $ resolved ;
104106}
105107
@@ -296,9 +298,16 @@ function delay(float $seconds): void
296298 * });
297299 * ```
298300 *
299- * @param callable(mixed ...$args):(\Generator<mixed,PromiseInterface,mixed,mixed>|mixed) $function
301+ * @template T
302+ * @template TYield
303+ * @template A1 (any number of function arguments, see https://github.com/phpstan/phpstan/issues/8214)
304+ * @template A2
305+ * @template A3
306+ * @template A4
307+ * @template A5
308+ * @param callable(A1, A2, A3, A4, A5):(\Generator<mixed, PromiseInterface<TYield>, TYield, PromiseInterface<T>|T>|PromiseInterface<T>|T) $function
300309 * @param mixed ...$args Optional list of additional arguments that will be passed to the given `$function` as is
301- * @return PromiseInterface<mixed >
310+ * @return PromiseInterface<T >
302311 * @since 3.0.0
303312 */
304313function coroutine (callable $ function , ...$ args ): PromiseInterface
@@ -315,7 +324,7 @@ function coroutine(callable $function, ...$args): PromiseInterface
315324
316325 $ promise = null ;
317326 $ deferred = new Deferred (function () use (&$ promise ) {
318- /** @var ?PromiseInterface $promise */
327+ /** @var ?PromiseInterface<T> $promise */
319328 if ($ promise instanceof PromiseInterface && \method_exists ($ promise , 'cancel ' )) {
320329 $ promise ->cancel ();
321330 }
@@ -336,7 +345,6 @@ function coroutine(callable $function, ...$args): PromiseInterface
336345 return ;
337346 }
338347
339- /** @var mixed $promise */
340348 $ promise = $ generator ->current ();
341349 if (!$ promise instanceof PromiseInterface) {
342350 $ next = null ;
@@ -346,6 +354,7 @@ function coroutine(callable $function, ...$args): PromiseInterface
346354 return ;
347355 }
348356
357+ /** @var PromiseInterface<TYield> $promise */
349358 assert ($ next instanceof \Closure);
350359 $ promise ->then (function ($ value ) use ($ generator , $ next ) {
351360 $ generator ->send ($ value );
@@ -364,12 +373,13 @@ function coroutine(callable $function, ...$args): PromiseInterface
364373}
365374
366375/**
367- * @param iterable<callable():PromiseInterface<mixed>> $tasks
368- * @return PromiseInterface<array<mixed>>
376+ * @template T
377+ * @param iterable<callable():(PromiseInterface<T>|T)> $tasks
378+ * @return PromiseInterface<array<T>>
369379 */
370380function parallel (iterable $ tasks ): PromiseInterface
371381{
372- /** @var array<int,PromiseInterface> $pending */
382+ /** @var array<int,PromiseInterface<T> > $pending */
373383 $ pending = [];
374384 $ deferred = new Deferred (function () use (&$ pending ) {
375385 foreach ($ pending as $ promise ) {
@@ -424,14 +434,15 @@ function parallel(iterable $tasks): PromiseInterface
424434}
425435
426436/**
427- * @param iterable<callable():PromiseInterface<mixed>> $tasks
428- * @return PromiseInterface<array<mixed>>
437+ * @template T
438+ * @param iterable<callable():(PromiseInterface<T>|T)> $tasks
439+ * @return PromiseInterface<array<T>>
429440 */
430441function series (iterable $ tasks ): PromiseInterface
431442{
432443 $ pending = null ;
433444 $ deferred = new Deferred (function () use (&$ pending ) {
434- /** @var ?PromiseInterface $pending */
445+ /** @var ?PromiseInterface<T> $pending */
435446 if ($ pending instanceof PromiseInterface && \method_exists ($ pending , 'cancel ' )) {
436447 $ pending ->cancel ();
437448 }
@@ -478,14 +489,15 @@ function series(iterable $tasks): PromiseInterface
478489}
479490
480491/**
481- * @param iterable<(callable():PromiseInterface<mixed>)|(callable(mixed):PromiseInterface<mixed>)> $tasks
482- * @return PromiseInterface<mixed>
492+ * @template T
493+ * @param iterable<(callable():(PromiseInterface<T>|T))|(callable(mixed):(PromiseInterface<T>|T))> $tasks
494+ * @return PromiseInterface<($tasks is non-empty-array|\Traversable ? T : null)>
483495 */
484496function waterfall (iterable $ tasks ): PromiseInterface
485497{
486498 $ pending = null ;
487499 $ deferred = new Deferred (function () use (&$ pending ) {
488- /** @var ?PromiseInterface $pending */
500+ /** @var ?PromiseInterface<T> $pending */
489501 if ($ pending instanceof PromiseInterface && \method_exists ($ pending , 'cancel ' )) {
490502 $ pending ->cancel ();
491503 }
0 commit comments