176176 * await($promise);
177177 * ```
178178 *
179- * @param callable $function
180- * @return callable(mixed ...): PromiseInterface<mixed>
179+ * @template T
180+ * @template A1 (any number of function arguments, see https://github.com/phpstan/phpstan/issues/8214)
181+ * @template A2
182+ * @template A3
183+ * @template A4
184+ * @template A5
185+ * @param callable(A1,A2,A3,A4,A5): (PromiseInterface<T>|T) $function
186+ * @return callable(A1=,A2=,A3=,A4=,A5=): PromiseInterface<T>
181187 * @since 4.0.0
182188 * @see coroutine()
183189 */
@@ -268,8 +274,9 @@ function async(callable $function): callable
268274 * }
269275 * ```
270276 *
271- * @param PromiseInterface $promise
272- * @return mixed returns whatever the promise resolves to
277+ * @template T
278+ * @param PromiseInterface<T> $promise
279+ * @return T returns whatever the promise resolves to
273280 * @throws \Exception when the promise is rejected with an `Exception`
274281 * @throws \Throwable when the promise is rejected with a `Throwable`
275282 * @throws \UnexpectedValueException when the promise is rejected with an unexpected value (Promise API v1 or v2 only)
@@ -279,6 +286,8 @@ function await(PromiseInterface $promise): mixed
279286 $ fiber = null ;
280287 $ resolved = false ;
281288 $ rejected = false ;
289+
290+ /** @var T $resolvedValue */
282291 $ resolvedValue = null ;
283292 $ rejectedThrowable = null ;
284293 $ lowLevelFiber = \Fiber::getCurrent ();
@@ -292,6 +301,7 @@ function (mixed $value) use (&$resolved, &$resolvedValue, &$fiber, $lowLevelFibe
292301 /** @var ?\Fiber<mixed,mixed,mixed,mixed> $fiber */
293302 if ($ fiber === null ) {
294303 $ resolved = true ;
304+ /** @var T $resolvedValue */
295305 $ resolvedValue = $ value ;
296306 return ;
297307 }
@@ -305,7 +315,7 @@ function (mixed $throwable) use (&$rejected, &$rejectedThrowable, &$fiber, $lowL
305315
306316 if (!$ throwable instanceof \Throwable) {
307317 $ throwable = new \UnexpectedValueException (
308- 'Promise rejected with unexpected value of type ' . (is_object ($ throwable ) ? get_class ($ throwable ) : gettype ($ throwable ))
318+ 'Promise rejected with unexpected value of type ' . (is_object ($ throwable ) ? get_class ($ throwable ) : gettype ($ throwable )) /** @phpstan-ignore-line */
309319 );
310320
311321 // avoid garbage references by replacing all closures in call stack.
@@ -592,9 +602,16 @@ function delay(float $seconds): void
592602 * });
593603 * ```
594604 *
595- * @param callable(mixed ...$args):(\Generator<mixed,PromiseInterface,mixed,mixed>|mixed) $function
605+ * @template T
606+ * @template TYield
607+ * @template A1 (any number of function arguments, see https://github.com/phpstan/phpstan/issues/8214)
608+ * @template A2
609+ * @template A3
610+ * @template A4
611+ * @template A5
612+ * @param callable(A1, A2, A3, A4, A5):(\Generator<mixed, PromiseInterface<TYield>, TYield, PromiseInterface<T>|T>|PromiseInterface<T>|T) $function
596613 * @param mixed ...$args Optional list of additional arguments that will be passed to the given `$function` as is
597- * @return PromiseInterface<mixed >
614+ * @return PromiseInterface<T >
598615 * @since 3.0.0
599616 */
600617function coroutine (callable $ function , mixed ...$ args ): PromiseInterface
@@ -611,7 +628,7 @@ function coroutine(callable $function, mixed ...$args): PromiseInterface
611628
612629 $ promise = null ;
613630 $ deferred = new Deferred (function () use (&$ promise ) {
614- /** @var ?PromiseInterface $promise */
631+ /** @var ?PromiseInterface<T> $promise */
615632 if ($ promise instanceof PromiseInterface && \method_exists ($ promise , 'cancel ' )) {
616633 $ promise ->cancel ();
617634 }
@@ -632,7 +649,6 @@ function coroutine(callable $function, mixed ...$args): PromiseInterface
632649 return ;
633650 }
634651
635- /** @var mixed $promise */
636652 $ promise = $ generator ->current ();
637653 if (!$ promise instanceof PromiseInterface) {
638654 $ next = null ;
@@ -642,6 +658,7 @@ function coroutine(callable $function, mixed ...$args): PromiseInterface
642658 return ;
643659 }
644660
661+ /** @var PromiseInterface<TYield> $promise */
645662 assert ($ next instanceof \Closure);
646663 $ promise ->then (function ($ value ) use ($ generator , $ next ) {
647664 $ generator ->send ($ value );
@@ -660,12 +677,13 @@ function coroutine(callable $function, mixed ...$args): PromiseInterface
660677}
661678
662679/**
663- * @param iterable<callable():PromiseInterface<mixed>> $tasks
664- * @return PromiseInterface<array<mixed>>
680+ * @template T
681+ * @param iterable<callable():(PromiseInterface<T>|T)> $tasks
682+ * @return PromiseInterface<array<T>>
665683 */
666684function parallel (iterable $ tasks ): PromiseInterface
667685{
668- /** @var array<int,PromiseInterface> $pending */
686+ /** @var array<int,PromiseInterface<T> > $pending */
669687 $ pending = [];
670688 $ deferred = new Deferred (function () use (&$ pending ) {
671689 foreach ($ pending as $ promise ) {
@@ -720,14 +738,15 @@ function parallel(iterable $tasks): PromiseInterface
720738}
721739
722740/**
723- * @param iterable<callable():PromiseInterface<mixed>> $tasks
724- * @return PromiseInterface<array<mixed>>
741+ * @template T
742+ * @param iterable<callable():(PromiseInterface<T>|T)> $tasks
743+ * @return PromiseInterface<array<T>>
725744 */
726745function series (iterable $ tasks ): PromiseInterface
727746{
728747 $ pending = null ;
729748 $ deferred = new Deferred (function () use (&$ pending ) {
730- /** @var ?PromiseInterface $pending */
749+ /** @var ?PromiseInterface<T> $pending */
731750 if ($ pending instanceof PromiseInterface && \method_exists ($ pending , 'cancel ' )) {
732751 $ pending ->cancel ();
733752 }
@@ -774,14 +793,15 @@ function series(iterable $tasks): PromiseInterface
774793}
775794
776795/**
777- * @param iterable<(callable():PromiseInterface<mixed>)|(callable(mixed):PromiseInterface<mixed>)> $tasks
778- * @return PromiseInterface<mixed>
796+ * @template T
797+ * @param iterable<(callable():(PromiseInterface<T>|T))|(callable(mixed):(PromiseInterface<T>|T))> $tasks
798+ * @return PromiseInterface<($tasks is non-empty-array|\Traversable ? T : null)>
779799 */
780800function waterfall (iterable $ tasks ): PromiseInterface
781801{
782802 $ pending = null ;
783803 $ deferred = new Deferred (function () use (&$ pending ) {
784- /** @var ?PromiseInterface $pending */
804+ /** @var ?PromiseInterface<T> $pending */
785805 if ($ pending instanceof PromiseInterface && \method_exists ($ pending , 'cancel ' )) {
786806 $ pending ->cancel ();
787807 }
0 commit comments