From 2b4a974134a49083fd55acc5414105d6970d5127 Mon Sep 17 00:00:00 2001 From: USAMI Kenta Date: Thu, 9 Jul 2026 02:15:54 +0900 Subject: [PATCH] Use list-shapes for functionMap return types that are guaranteed lists These functions return arrays whose keys are always 0..n-1 in ascending order, so spell them as list{...} instead of array{...} / array{0: ...}. Currently a semantic no-op (both spellings resolve to the same type), but it keeps these signatures list-typed under the stricter array-shape semantics proposed in phpstan/phpstan#14939, where plain array-shapes no longer guarantee key order. Refs https://github.com/phpstan/phpstan/discussions/14939 --- resources/functionMap.php | 26 +++++++++++++------------- resources/functionMap_php80delta.php | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/resources/functionMap.php b/resources/functionMap.php index f3b563aa484..07bda44a29e 100644 --- a/resources/functionMap.php +++ b/resources/functionMap.php @@ -2393,7 +2393,7 @@ 'ffmpeg_movie::hasAudio' => ['bool'], 'ffmpeg_movie::hasVideo' => ['bool'], 'fgetc' => ['string|false', 'fp'=>'resource'], -'fgetcsv' => ['non-empty-list|array{0: null}|false|null', 'fp'=>'resource', 'length='=>'0|positive-int|null', 'delimiter='=>'string', 'enclosure='=>'string', 'escape='=>'string'], +'fgetcsv' => ['non-empty-list|list{null}|false|null', 'fp'=>'resource', 'length='=>'0|positive-int|null', 'delimiter='=>'string', 'enclosure='=>'string', 'escape='=>'string'], 'fgets' => ['string|false', 'fp'=>'resource', 'length='=>'0|positive-int'], 'fgetss' => ['string|false', 'fp'=>'resource', 'length='=>'0|positive-int', 'allowable_tags='=>'string'], 'file' => ['list|false', 'filename'=>'string', 'flags='=>'int-mask', 'context='=>'resource'], @@ -3401,7 +3401,7 @@ 'hexdec' => ['int|float', 'hexadecimal_number'=>'string'], 'highlight_file' => ['string|bool', 'file_name'=>'string', 'return='=>'bool'], 'highlight_string' => ['string|bool', 'string'=>'string', 'return='=>'bool'], -'hrtime' => ['array{0:int,1:int}|int|float|false', 'get_as_number='=>'bool'], +'hrtime' => ['list{int,int}|int|float|false', 'get_as_number='=>'bool'], 'HRTime\PerformanceCounter::getElapsedTicks' => ['int'], 'HRTime\PerformanceCounter::getFrequency' => ['int'], 'HRTime\PerformanceCounter::getLastElapsedTicks' => ['int'], @@ -3995,8 +3995,8 @@ 'image_type_to_mime_type' => ['string', 'imagetype'=>'int'], 'imageaffine' => ['resource|false', 'src'=>'resource', 'affine'=>'array', 'clip='=>'array'], 'imageaffineconcat' => ['array', 'm1'=>'array', 'm2'=>'array'], -'imageaffinematrixconcat' => ['array{0:float,1:float,2:float,3:float,4:float,5:float}|false', 'm1'=>'array', 'm2'=>'array'], -'imageaffinematrixget' => ['array{0:float,1:float,2:float,3:float,4:float,5:float}|false', 'type'=>'int', 'options'=>'array|float'], +'imageaffinematrixconcat' => ['list{float,float,float,float,float,float}|false', 'm1'=>'array', 'm2'=>'array'], +'imageaffinematrixget' => ['list{float,float,float,float,float,float}|false', 'type'=>'int', 'options'=>'array|float'], 'imagealphablending' => ['bool', 'im'=>'resource', 'on'=>'bool'], 'imageantialias' => ['bool', 'im'=>'resource', 'on'=>'bool'], 'imagearc' => ['bool', 'im'=>'resource', 'cx'=>'int', 'cy'=>'int', 'w'=>'int', 'h'=>'int', 's'=>'int', 'e'=>'int', 'col'=>'int'], @@ -4143,9 +4143,9 @@ 'Imagick::colorMatrixImage' => ['bool', 'color_matrix'=>'array'], 'Imagick::combineImages' => ['Imagick', 'channeltype'=>'Imagick::CHANNEL_*'], 'Imagick::commentImage' => ['bool', 'comment'=>'string'], -'Imagick::compareImageChannels' => ['array{Imagick,float}', 'image'=>'imagick', 'channeltype'=>'Imagick::CHANNEL_*', 'metrictype'=>'Imagick::METRIC_*'], +'Imagick::compareImageChannels' => ['list{Imagick,float}', 'image'=>'imagick', 'channeltype'=>'Imagick::CHANNEL_*', 'metrictype'=>'Imagick::METRIC_*'], 'Imagick::compareImageLayers' => ['Imagick', 'method'=>'Imagick::LAYERMETHOD_*'], -'Imagick::compareImages' => ['array{Imagick,float}', 'compare'=>'imagick', 'metric'=>'Imagick::METRIC_*'], +'Imagick::compareImages' => ['list{Imagick,float}', 'compare'=>'imagick', 'metric'=>'Imagick::METRIC_*'], 'Imagick::compositeImage' => ['bool', 'composite_object'=>'imagick', 'composite'=>'Imagick::COMPOSITE_*', 'x'=>'int', 'y'=>'int', 'channel='=>'Imagick::CHANNEL_*'], 'Imagick::compositeImageGravity' => ['bool', 'imagick'=>'Imagick', 'COMPOSITE_CONSTANT'=>'int', 'GRAVITY_CONSTANT'=>'int'], 'Imagick::contrastImage' => ['bool', 'sharpen'=>'bool'], @@ -8192,7 +8192,7 @@ 'preg_replace' => ['string|array|null', 'regex'=>'string|array', 'replace'=>'string|array', 'subject'=>'string|array', 'limit='=>'int', '&w_count='=>'int'], 'preg_replace_callback' => ['string|array|null', 'regex'=>'string|array', 'callback'=>'callable(array):string', 'subject'=>'string|array', 'limit='=>'int', '&w_count='=>'int'], 'preg_replace_callback_array' => ['string|array|null', 'pattern'=>'array', 'subject'=>'string|array', 'limit='=>'int', '&w_count='=>'int'], -'preg_split' => ['list|list}>|false', 'pattern'=>'string', 'subject'=>'string', 'limit='=>'?int', 'flags='=>'int'], +'preg_split' => ['list|list}>|false', 'pattern'=>'string', 'subject'=>'string', 'limit='=>'?int', 'flags='=>'int'], 'prev' => ['mixed', '&rw_array_arg'=>'array|object'], 'print_r' => ['string|true', 'var'=>'mixed', 'return='=>'bool'], 'printf' => ['int', 'format'=>'string', '...values='=>'__stringAndStringable|int|float|null|bool'], @@ -8641,7 +8641,7 @@ 'Redis::geoadd' => ['__benevolent', 'key'=>'string', 'lng'=>'float', 'lat'=>'float', 'member'=>'string', '...other_triples_and_options='=>'mixed'], 'Redis::geodist' => ['__benevolent', 'key'=>'string', 'member'=>'string', '...other_members='=>'string'], 'Redis::geohash' => ['__benevolent|false>', 'key'=>'string', 'member'=>'string', '...other_members='=>'string'], -'Redis::geopos' => ['__benevolent|false>', 'key'=>'string', 'member'=>'string', '...other_members'=>'string'], +'Redis::geopos' => ['__benevolent|false>', 'key'=>'string', 'member'=>'string', '...other_members'=>'string'], 'Redis::georadius' => ['__benevolent>', 'key'=>'string', 'lng'=>'float', 'lat'=>'float', 'radius'=>'float', 'unit'=>'string', 'options='=>'array'], 'Redis::georadiusbymember' => ['__benevolent>', 'key'=>'string', 'lng'=>'float', 'lat'=>'float', 'radius'=>'float', 'unit'=>'string', 'options='=>'array'], 'Redis::georadiusbymember_ro' => ['__benevolent>', 'key'=>'string', 'lng'=>'float', 'lat'=>'float', 'radius'=>'float', 'unit'=>'string', 'options='=>'array'], @@ -8656,7 +8656,7 @@ 'Redis::getOption' => ['int', 'name'=>'int'], 'Redis::getRange' => ['__benevolent', 'key'=>'string', 'start'=>'int', 'end'=>'int'], 'Redis::getset' => ['__benevolent', 'key'=>'string', 'value'=>'mixed'], -'Redis::getTransferredBytes' => ['array'], +'Redis::getTransferredBytes' => ['array'], 'Redis::hDel' => ['__benevolent', 'key'=>'string', 'field'=>'string', '...other_fields='=>'string'], 'Redis::hExists' => ['__benevolent', 'key'=>'string', 'field'=>'string'], 'Redis::hGet' => ['__benevolent', 'key'=>'string', 'member'=>'string'], @@ -8773,7 +8773,7 @@ 'Redis::sUnionStore' => ['__benevolent', 'dst'=>'string', 'key'=>'string', '...other_keys='=>'string'], 'Redis::sunsubscribe' => ['__benevolent', 'channels'=>'string[]'], 'Redis::swapdb' => ['__benevolent', 'src'=>'int', 'dst'=>'int'], -'Redis::time' => ['__benevolent'], +'Redis::time' => ['__benevolent'], 'Redis::ttl' => ['__benevolent', 'key'=>'string'], 'Redis::type' => ['__benevolent', 'key'=>'string'], 'Redis::unlink' => ['__benevolent', 'key'=>'string[]|string', '...other_keys'=>'string'], @@ -9936,7 +9936,7 @@ 'SplFileObject::fflush' => ['bool'], 'SplFileObject::fgetc' => ['string|false'], // Do not believe https://www.php.net/manual/en/splfileobject.fgetcsv#refsect1-splfileobject.fgetcsv-returnvalues -'SplFileObject::fgetcsv' => ['non-empty-list|array{0: null}|false|null', 'delimiter='=>'string', 'enclosure='=>'string', 'escape='=>'string'], +'SplFileObject::fgetcsv' => ['non-empty-list|list{null}|false|null', 'delimiter='=>'string', 'enclosure='=>'string', 'escape='=>'string'], 'SplFileObject::fgets' => ['string'], 'SplFileObject::fgetss' => ['string|false', 'allowable_tags='=>'string'], 'SplFileObject::flock' => ['bool', 'operation'=>'int-mask', '&w_wouldblock='=>'0|1'], @@ -10831,7 +10831,7 @@ 'SyncSharedMemory::size' => ['bool'], 'SyncSharedMemory::write' => ['', 'string='=>'string', 'start='=>'int'], 'sys_get_temp_dir' => ['string'], -'sys_getloadavg' => ['array{float,float,float}|false'], +'sys_getloadavg' => ['list{float,float,float}|false'], 'syslog' => ['bool', 'priority'=>'int', 'message'=>'string'], 'system' => ['string|false', 'command'=>'string', '&w_return_value='=>'int'], 'taint' => ['bool', '&rw_string'=>'string', '&...w_other_strings='=>'string'], @@ -10963,7 +10963,7 @@ 'timezone_transitions_get' => ['list|false', 'object'=>'DateTimeZone', 'timestamp_begin='=>'int', 'timestamp_end='=>'int'], 'timezone_version_get' => ['string'], 'tmpfile' => ['__benevolent'], -'token_get_all' => ['list', 'source'=>'string', 'flags='=>'int'], +'token_get_all' => ['list', 'source'=>'string', 'flags='=>'int'], 'token_name' => ['non-falsy-string', 'type'=>'int'], 'TokyoTyrant::__construct' => ['void', 'host='=>'string', 'port='=>'int', 'options='=>'array'], 'TokyoTyrant::add' => ['int|float', 'key'=>'string', 'increment'=>'float', 'type='=>'int'], diff --git a/resources/functionMap_php80delta.php b/resources/functionMap_php80delta.php index 4e3179a3198..e27225eabf1 100644 --- a/resources/functionMap_php80delta.php +++ b/resources/functionMap_php80delta.php @@ -46,7 +46,7 @@ 'error_log' => ['bool', 'message'=>'string', 'message_type='=>'0|1|3|4', 'destination='=>'string', 'extra_headers='=>'string'], 'explode' => ['list', 'separator'=>'non-empty-string', 'str'=>'string', 'limit='=>'int'], 'fdiv' => ['float', 'dividend'=>'float', 'divisor'=>'float'], - 'fgetcsv' => ['non-empty-list|array{0: null}|false', 'fp'=>'resource', 'length='=>'0|positive-int|null', 'delimiter='=>'string', 'enclosure='=>'string', 'escape='=>'string'], + 'fgetcsv' => ['non-empty-list|list{null}|false', 'fp'=>'resource', 'length='=>'0|positive-int|null', 'delimiter='=>'string', 'enclosure='=>'string', 'escape='=>'string'], 'filter_input' => ['mixed', 'type'=>'INPUT_GET|INPUT_POST|INPUT_COOKIE|INPUT_SERVER|INPUT_ENV', 'variable_name'=>'string', 'filter='=>'int', 'options='=>'array|int'], 'filter_input_array' => ['array|false|null', 'type'=>'INPUT_GET|INPUT_POST|INPUT_COOKIE|INPUT_SERVER|INPUT_ENV', 'definition='=>'int|array', 'add_empty='=>'bool'], 'floor' => ['float', 'number'=>'float'],