From 076eeb15755b096263e044dcd84ddff1e2045404 Mon Sep 17 00:00:00 2001 From: Valentin Udaltsov Date: Thu, 1 May 2025 15:27:19 +0300 Subject: [PATCH 1/2] Replace \Closure(...) with \Closure(mixed...) See https://github.com/phpstan/phpstan/issues/12954 --- README.md | 4 ++-- src/functions.php | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 15d2af30..a1fe8575 100644 --- a/README.md +++ b/README.md @@ -447,8 +447,8 @@ time differences independent of wall-time. ```php /** * @template TReturn - * @param Closure(...):TReturn $closure - * @return Closure(...):TReturn + * @param Closure(mixed...):TReturn $closure + * @return Closure(mixed...):TReturn */ function weakClosure(Closure $closure): Closure ``` diff --git a/src/functions.php b/src/functions.php index 0d3bfcce..05dced59 100644 --- a/src/functions.php +++ b/src/functions.php @@ -11,7 +11,7 @@ * * @template T * - * @param \Closure(...):T $closure + * @param \Closure(mixed...):T $closure * @param mixed ...$args Arguments forwarded to the closure when starting the fiber. * * @return Future @@ -131,9 +131,9 @@ function trapSignal(int|array $signals, bool $reference = true, ?Cancellation $c * * @template TReturn * - * @param \Closure(...):TReturn $closure + * @param \Closure(mixed...):TReturn $closure * - * @return \Closure(...):TReturn + * @return \Closure(mixed...):TReturn */ function weakClosure(\Closure $closure): \Closure { @@ -167,7 +167,7 @@ function weakClosure(\Closure $closure): \Closure throw new \RuntimeException('Unable to rebind closure scoped to ' . ($scope?->name ?? $that::class)); } - /** @var \Closure(...):TReturn */ + /** @var \Closure(mixed...):TReturn */ return static function (mixed ...$args) use ($reference, $closure, $useBindTo): mixed { $that = $reference->get(); if (!$that) { From 02d56d707b97f2d44f228653d5d7bddaa0806678 Mon Sep 17 00:00:00 2001 From: Valentin Udaltsov Date: Fri, 2 May 2025 13:18:39 +0300 Subject: [PATCH 2/2] Use Closure(never, never) for async to satisfy PHPStan You cannot pass a Closure with narrower parameters to a Closure with wider parameters, since parameters are contravariant. Here's the possible solution: - for PHPStan use a Closure with a bunch of never parameters for to indicate that Closure might have parameters with any wider types and suppress the place where it is invoked, - for Psalm keep the current Closure(...) syntax, because Psalm does not allow to have never parameters. https://phpstan.org/r/4e98ea03-a863-4b39-8fcf-07cfdc2e8ea4 https://psalm.dev/r/cda9b2565b --- README.md | 4 ++-- src/functions.php | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index a1fe8575..15d2af30 100644 --- a/README.md +++ b/README.md @@ -447,8 +447,8 @@ time differences independent of wall-time. ```php /** * @template TReturn - * @param Closure(mixed...):TReturn $closure - * @return Closure(mixed...):TReturn + * @param Closure(...):TReturn $closure + * @return Closure(...):TReturn */ function weakClosure(Closure $closure): Closure ``` diff --git a/src/functions.php b/src/functions.php index 05dced59..98fecf4c 100644 --- a/src/functions.php +++ b/src/functions.php @@ -11,7 +11,8 @@ * * @template T * - * @param \Closure(mixed...):T $closure + * @psalm-param \Closure(...): T $closure + * @phpstan-param \Closure(never, never, never, never, never): T $closure * @param mixed ...$args Arguments forwarded to the closure when starting the fiber. * * @return Future @@ -131,9 +132,9 @@ function trapSignal(int|array $signals, bool $reference = true, ?Cancellation $c * * @template TReturn * - * @param \Closure(mixed...):TReturn $closure + * @param \Closure(...):TReturn $closure * - * @return \Closure(mixed...):TReturn + * @return \Closure(...):TReturn */ function weakClosure(\Closure $closure): \Closure { @@ -167,7 +168,7 @@ function weakClosure(\Closure $closure): \Closure throw new \RuntimeException('Unable to rebind closure scoped to ' . ($scope?->name ?? $that::class)); } - /** @var \Closure(mixed...):TReturn */ + /** @var \Closure(...):TReturn */ return static function (mixed ...$args) use ($reference, $closure, $useBindTo): mixed { $that = $reference->get(); if (!$that) {