From 1005bc7da7cd1d67953dbb7e4318e7f0133efdee Mon Sep 17 00:00:00 2001 From: Cees-Jan Kiewiet Date: Fri, 10 Jan 2025 07:27:53 +0100 Subject: [PATCH] [2.x] Ensure void return type translates to null --- Makefile | 2 +- composer.json | 26 ++++-- composer.lock | 193 +++++++++++++++++++++++++++--------------- etc/qa/phpstan.neon | 8 ++ src/PoolInterface.php | 22 +++-- tests/MockPool.php | 16 +++- tests/Types.php | 8 ++ 7 files changed, 192 insertions(+), 83 deletions(-) diff --git a/Makefile b/Makefile index de846bf..13dcf8b 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ else -v "`pwd`:`pwd`" \ -v "${COMPOSER_CACHE_DIR}:${COMPOSER_CONTAINER_CACHE_DIR}" \ -w "`pwd`" \ - "ghcr.io/wyrihaximusnet/php:${PHP_VERSION}-nts-alpine${SLIM_DOCKER_IMAGE}-dev" + "ghcr.io/wyrihaximusnet/php:${PHP_VERSION}-zts-alpine${SLIM_DOCKER_IMAGE}-dev" endif ifneq (,$(findstring icrosoft,$(shell cat /proc/version))) diff --git a/composer.json b/composer.json index 000fd31..ff13cf6 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "react-parallel/contracts", - "description": "Interfaces for ReactPHP ext-parallel related packages", + "description": "\ud83d\udcdc Interfaces for ReactPHP ext-parallel related packages", "license": "MIT", "authors": [ { @@ -14,6 +14,8 @@ "wyrihaximus/pool-info": "^2.0.0" }, "require-dev": { + "ext-parallel": "*", + "react-parallel/stubs": "^1.2", "wyrihaximus/async-test-utilities": "^8.0.5" }, "autoload": { @@ -27,15 +29,23 @@ } }, "config": { - "platform": { - "php": "8.2.13" - }, - "sort-packages": true, "allow-plugins": { - "infection/extension-installer": true, "dealerdirect/phpcodesniffer-composer-installer": true, + "ergebnis/composer-normalize": true, "icanhazstring/composer-unused": true, - "ergebnis/composer-normalize": true - } + "infection/extension-installer": true + }, + "platform": { + "php": "8.2.13" + }, + "sort-packages": true + }, + "scripts": { + "post-install-cmd": [ + "composer normalize" + ], + "post-update-cmd": [ + "composer normalize" + ] } } diff --git a/composer.lock b/composer.lock index 5d883f8..969272b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "850d98b4d03f4f8e85fa8d97831a618f", + "content-hash": "5d20365300b74fc7a45b4a1b0387cbb8", "packages": [ { "name": "wyrihaximus/iterator-or-array-to-array", @@ -726,16 +726,16 @@ }, { "name": "composer/ca-bundle", - "version": "1.5.4", + "version": "1.5.5", "source": { "type": "git", "url": "https://github.com/composer/ca-bundle.git", - "reference": "bc0593537a463e55cadf45fd938d23b75095b7e1" + "reference": "08c50d5ec4c6ced7d0271d2862dec8c1033283e6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/ca-bundle/zipball/bc0593537a463e55cadf45fd938d23b75095b7e1", - "reference": "bc0593537a463e55cadf45fd938d23b75095b7e1", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/08c50d5ec4c6ced7d0271d2862dec8c1033283e6", + "reference": "08c50d5ec4c6ced7d0271d2862dec8c1033283e6", "shasum": "" }, "require": { @@ -782,7 +782,7 @@ "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/ca-bundle/issues", - "source": "https://github.com/composer/ca-bundle/tree/1.5.4" + "source": "https://github.com/composer/ca-bundle/tree/1.5.5" }, "funding": [ { @@ -798,7 +798,7 @@ "type": "tidelift" } ], - "time": "2024-11-27T15:35:25+00:00" + "time": "2025-01-08T16:17:16+00:00" }, { "name": "composer/class-map-generator", @@ -2082,16 +2082,16 @@ }, { "name": "ergebnis/phpstan-rules", - "version": "2.5.0", + "version": "2.5.2", "source": { "type": "git", "url": "https://github.com/ergebnis/phpstan-rules.git", - "reference": "ffbc24d0d7e7b0d2b45f524753c20d83a83f66de" + "reference": "2754afbaf4f31ec82aab1cc0e2fdd68130a974c8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/phpstan-rules/zipball/ffbc24d0d7e7b0d2b45f524753c20d83a83f66de", - "reference": "ffbc24d0d7e7b0d2b45f524753c20d83a83f66de", + "url": "https://api.github.com/repos/ergebnis/phpstan-rules/zipball/2754afbaf4f31ec82aab1cc0e2fdd68130a974c8", + "reference": "2754afbaf4f31ec82aab1cc0e2fdd68130a974c8", "shasum": "" }, "require": { @@ -2101,16 +2101,18 @@ }, "require-dev": { "doctrine/orm": "^2.20.0 || ^3.3.0", - "ergebnis/composer-normalize": "^2.44.0", + "ergebnis/composer-normalize": "^2.45.0", "ergebnis/license": "^2.6.0", "ergebnis/php-cs-fixer-config": "^6.39.0", "ergebnis/phpunit-slow-test-detector": "^2.17.0", "nette/di": "^3.1.10", "nikic/php-parser": "^4.19.4", + "phpstan/extension-installer": "^1.4.3", "phpstan/phpstan-deprecation-rules": "^1.2.1", "phpstan/phpstan-strict-rules": "^1.6.1", "phpunit/phpunit": "^9.6.21", "psr/container": "^2.0.2", + "symfony/finder": "^5.4.45", "symfony/process": "^5.4.47" }, "type": "phpstan-extension", @@ -2148,7 +2150,7 @@ "security": "https://github.com/ergebnis/phpstan-rules/blob/main/.github/SECURITY.md", "source": "https://github.com/ergebnis/phpstan-rules" }, - "time": "2024-12-01T16:44:41+00:00" + "time": "2025-01-08T09:28:54+00:00" }, { "name": "ergebnis/phpunit-slow-test-detector", @@ -5378,16 +5380,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.12.13", + "version": "1.12.15", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "9b469068840cfa031e1deaf2fa1886d00e20680f" + "reference": "c91d4e8bc056f46cf653656e6f71004b254574d1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/9b469068840cfa031e1deaf2fa1886d00e20680f", - "reference": "9b469068840cfa031e1deaf2fa1886d00e20680f", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/c91d4e8bc056f46cf653656e6f71004b254574d1", + "reference": "c91d4e8bc056f46cf653656e6f71004b254574d1", "shasum": "" }, "require": { @@ -5432,7 +5434,7 @@ "type": "github" } ], - "time": "2024-12-17T17:00:20+00:00" + "time": "2025-01-05T16:40:22+00:00" }, { "name": "phpstan/phpstan-deprecation-rules", @@ -6659,6 +6661,59 @@ ], "time": "2024-04-27T21:32:50+00:00" }, + { + "name": "react-parallel/stubs", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp-parallel/stubs.git", + "reference": "ed526a6d4462938094582fb88f1e54d55ae58d18" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp-parallel/stubs/zipball/ed526a6d4462938094582fb88f1e54d55ae58d18", + "reference": "ed526a6d4462938094582fb88f1e54d55ae58d18", + "shasum": "" + }, + "require": { + "ext-parallel": "*", + "php": "^8.1" + }, + "require-dev": { + "wyrihaximus/async-test-utilities": "^5 || ^7.2" + }, + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Cees-Jan Kiewiet", + "email": "ceesjank@gmail.com", + "homepage": "http://wyrihaximus.net/" + } + ], + "description": "🫏 Stubs (for PHPstan)", + "support": { + "issues": "https://github.com/reactphp-parallel/stubs/issues", + "source": "https://github.com/reactphp-parallel/stubs/tree/1.2.0" + }, + "funding": [ + { + "url": "https://github.com/WyriHaximus", + "type": "github" + } + ], + "time": "2025-01-09T15:41:29+00:00" + }, { "name": "react/async", "version": "v4.3.0", @@ -8761,16 +8816,16 @@ }, { "name": "symfony/console", - "version": "v6.4.15", + "version": "v6.4.17", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "f1fc6f47283e27336e7cebb9e8946c8de7bff9bd" + "reference": "799445db3f15768ecc382ac5699e6da0520a0a04" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/f1fc6f47283e27336e7cebb9e8946c8de7bff9bd", - "reference": "f1fc6f47283e27336e7cebb9e8946c8de7bff9bd", + "url": "https://api.github.com/repos/symfony/console/zipball/799445db3f15768ecc382ac5699e6da0520a0a04", + "reference": "799445db3f15768ecc382ac5699e6da0520a0a04", "shasum": "" }, "require": { @@ -8835,7 +8890,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.15" + "source": "https://github.com/symfony/console/tree/v6.4.17" }, "funding": [ { @@ -8851,7 +8906,7 @@ "type": "tidelift" } ], - "time": "2024-11-06T14:19:14+00:00" + "time": "2024-12-07T12:07:30+00:00" }, { "name": "symfony/dependency-injection", @@ -8952,12 +9007,12 @@ }, "type": "library", "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, "branch-alias": { "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" } }, "autoload": { @@ -9068,16 +9123,16 @@ }, { "name": "symfony/finder", - "version": "v7.2.0", + "version": "v7.2.2", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "6de263e5868b9a137602dd1e33e4d48bfae99c49" + "reference": "87a71856f2f56e4100373e92529eed3171695cfb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/6de263e5868b9a137602dd1e33e4d48bfae99c49", - "reference": "6de263e5868b9a137602dd1e33e4d48bfae99c49", + "url": "https://api.github.com/repos/symfony/finder/zipball/87a71856f2f56e4100373e92529eed3171695cfb", + "reference": "87a71856f2f56e4100373e92529eed3171695cfb", "shasum": "" }, "require": { @@ -9112,7 +9167,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.2.0" + "source": "https://github.com/symfony/finder/tree/v7.2.2" }, "funding": [ { @@ -9128,7 +9183,7 @@ "type": "tidelift" } ], - "time": "2024-10-23T06:56:12+00:00" + "time": "2024-12-30T19:00:17+00:00" }, { "name": "symfony/polyfill-ctype", @@ -9895,22 +9950,22 @@ }, { "name": "symfony/property-info", - "version": "v7.2.1", + "version": "v7.2.2", "source": { "type": "git", "url": "https://github.com/symfony/property-info.git", - "reference": "65fb9be15380f949d72ff405473cce733364b8b4" + "reference": "1dfeb0dac7a99f7b3be42db9ccc299c5a6483fcf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-info/zipball/65fb9be15380f949d72ff405473cce733364b8b4", - "reference": "65fb9be15380f949d72ff405473cce733364b8b4", + "url": "https://api.github.com/repos/symfony/property-info/zipball/1dfeb0dac7a99f7b3be42db9ccc299c5a6483fcf", + "reference": "1dfeb0dac7a99f7b3be42db9ccc299c5a6483fcf", "shasum": "" }, "require": { "php": ">=8.2", "symfony/string": "^6.4|^7.0", - "symfony/type-info": "^7.1" + "symfony/type-info": "~7.1.9|^7.2.2" }, "conflict": { "phpdocumentor/reflection-docblock": "<5.2", @@ -9958,7 +10013,7 @@ "validator" ], "support": { - "source": "https://github.com/symfony/property-info/tree/v7.2.1" + "source": "https://github.com/symfony/property-info/tree/v7.2.2" }, "funding": [ { @@ -9974,7 +10029,7 @@ "type": "tidelift" } ], - "time": "2024-12-07T08:50:44+00:00" + "time": "2024-12-31T11:04:50+00:00" }, { "name": "symfony/serializer", @@ -10098,12 +10153,12 @@ }, "type": "library", "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, "branch-alias": { "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" } }, "autoload": { @@ -10159,16 +10214,16 @@ }, { "name": "symfony/stopwatch", - "version": "v7.2.0", + "version": "v7.2.2", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "696f418b0d722a4225e1c3d95489d262971ca924" + "reference": "e46690d5b9d7164a6d061cab1e8d46141b9f49df" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/696f418b0d722a4225e1c3d95489d262971ca924", - "reference": "696f418b0d722a4225e1c3d95489d262971ca924", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/e46690d5b9d7164a6d061cab1e8d46141b9f49df", + "reference": "e46690d5b9d7164a6d061cab1e8d46141b9f49df", "shasum": "" }, "require": { @@ -10201,7 +10256,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v7.2.0" + "source": "https://github.com/symfony/stopwatch/tree/v7.2.2" }, "funding": [ { @@ -10217,7 +10272,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:21:43+00:00" + "time": "2024-12-18T14:28:33+00:00" }, { "name": "symfony/string", @@ -10325,12 +10380,12 @@ }, "type": "library", "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, "branch-alias": { "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" } }, "autoload": { @@ -10386,16 +10441,16 @@ }, { "name": "symfony/type-info", - "version": "v7.2.1", + "version": "v7.2.2", "source": { "type": "git", "url": "https://github.com/symfony/type-info.git", - "reference": "4f402070b08ad0b87e9cadbb07b87fb36061e6e4" + "reference": "3b5a17470fff0034f25fd4287cbdaa0010d2f749" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/type-info/zipball/4f402070b08ad0b87e9cadbb07b87fb36061e6e4", - "reference": "4f402070b08ad0b87e9cadbb07b87fb36061e6e4", + "url": "https://api.github.com/repos/symfony/type-info/zipball/3b5a17470fff0034f25fd4287cbdaa0010d2f749", + "reference": "3b5a17470fff0034f25fd4287cbdaa0010d2f749", "shasum": "" }, "require": { @@ -10441,7 +10496,7 @@ "type" ], "support": { - "source": "https://github.com/symfony/type-info/tree/v7.2.1" + "source": "https://github.com/symfony/type-info/tree/v7.2.2" }, "funding": [ { @@ -10457,20 +10512,20 @@ "type": "tidelift" } ], - "time": "2024-12-11T07:49:41+00:00" + "time": "2024-12-20T13:38:37+00:00" }, { "name": "symfony/validator", - "version": "v7.2.0", + "version": "v7.2.2", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "ddad20aa8cf7a45a9d6300e5776b8d252dc3524b" + "reference": "5c01f00fed258a987ef35f0fefcc069f84111cb4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/ddad20aa8cf7a45a9d6300e5776b8d252dc3524b", - "reference": "ddad20aa8cf7a45a9d6300e5776b8d252dc3524b", + "url": "https://api.github.com/repos/symfony/validator/zipball/5c01f00fed258a987ef35f0fefcc069f84111cb4", + "reference": "5c01f00fed258a987ef35f0fefcc069f84111cb4", "shasum": "" }, "require": { @@ -10538,7 +10593,7 @@ "description": "Provides tools to validate values", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/validator/tree/v7.2.0" + "source": "https://github.com/symfony/validator/tree/v7.2.2" }, "funding": [ { @@ -10554,7 +10609,7 @@ "type": "tidelift" } ], - "time": "2024-11-27T09:50:52+00:00" + "time": "2024-12-30T18:35:15+00:00" }, { "name": "symfony/var-exporter", @@ -11608,7 +11663,9 @@ "platform": { "php": "^8.2" }, - "platform-dev": {}, + "platform-dev": { + "ext-parallel": "*" + }, "platform-overrides": { "php": "8.2.13" }, diff --git a/etc/qa/phpstan.neon b/etc/qa/phpstan.neon index 9df0b91..2a1c205 100644 --- a/etc/qa/phpstan.neon +++ b/etc/qa/phpstan.neon @@ -1,4 +1,11 @@ parameters: + ignoreErrors: + - + message: '#sleep blocks the event loop#' + path: ../../tests/MockPool.php + - + message: '#sleep blocks the event loop#' + path: ../../tests/Types.php ergebnis: noExtends: classesAllowedToBeExtended: @@ -6,3 +13,4 @@ parameters: includes: - ../../vendor/wyrihaximus/async-test-utilities/rules.neon + - ../../vendor/react-parallel/stubs/extension.neon diff --git a/src/PoolInterface.php b/src/PoolInterface.php index c3226a1..ec2ba01 100644 --- a/src/PoolInterface.php +++ b/src/PoolInterface.php @@ -10,17 +10,29 @@ interface PoolInterface extends PoolInfoInterface { /** - * @param (Closure():T)|(Closure(A1):T)|(Closure(A1,A2):T)|(Closure(A1,A2,A3):T)|(Closure(A1,A2,A3,A4):T)|(Closure(A1,A2,A3,A4,A5):T) $callable - * @param array{}|array{A1}|array{A1,A2}|array{A1,A2,A3}|array{A1,A2,A3,A4}|array{A1,A2,A3,A4,A5} $args + * @param (Closure():T)|(Closure(A0):T)|(Closure(A0,A1):T)|(Closure(A0,A1,A2):T)|(Closure(A0,A1,A2,A3):T)|(Closure(A0,A1,A2,A3,A4):T)|(Closure():void)|(Closure(A0):void)|(Closure(A0,A1):void)|(Closure(A0,A1,A2):void)|(Closure(A0,A1,A2,A3):void)|(Closure(A0,A1,A2,A3,A4):void) $callable + * @param array{}|array{A0}|array{A0,A1}|array{A0,A1,A2}|array{A0,A1,A2,A3}|array{A0,A1,A2,A3,A4} $args * - * @return T + * @return ( + * $callable is (Closure():T) ? T : ( + * $callable is (Closure(A0):T) ? T : ( + * $callable is (Closure(A0,A1):T) ? T : ( + * $callable is (Closure(A0,A1,A2):T) ? T : ( + * $callable is (Closure(A0,A1,A2,A3):T) ? T : ( + * $callable is (Closure(A0,A1,A2,A3,A4):T) ? T : null + * ) + * ) + * ) + * ) + * ) + * ) * * @template T - * @template A1 (any number of function arguments, see https://github.com/phpstan/phpstan/issues/8214) + * @template A0 (any number of function arguments, see https://github.com/phpstan/phpstan/issues/8214) + * @template A1 * @template A2 * @template A3 * @template A4 - * @template A5 */ public function run(Closure $callable, array $args = []): mixed; diff --git a/tests/MockPool.php b/tests/MockPool.php index e1d47ea..88adaec 100644 --- a/tests/MockPool.php +++ b/tests/MockPool.php @@ -5,8 +5,12 @@ namespace ReactParallel\Tests\Contracts; use Closure; +use parallel\Future; use ReactParallel\Contracts\PoolInterface; +use function parallel\run; +use function sleep; + final class MockPool implements PoolInterface { /** @@ -22,7 +26,17 @@ public function info(): iterable */ public function run(Closure $callable, array $args = []): mixed { - return $callable(...$args); + $future = run($callable, $args); + + if ($future instanceof Future) { + while (! $future->done() && ! $future->cancelled()) { + sleep(1); + } + + return $future->value(); + } + + return null; } public function close(): bool diff --git a/tests/Types.php b/tests/Types.php index c892a11..dc1bd1b 100644 --- a/tests/Types.php +++ b/tests/Types.php @@ -8,6 +8,14 @@ $pool = new MockPool(); +assertType('Closure(): void', (static fn () => $pool->run(static function (): void { + sleep(1); +}))); + +assertType('Closure(): void', (static fn () => $pool->run(static function (int $time): void { + sleep($time); +}, [1]))); + assertType('true', $pool->run(static function (): bool { return true; }));