← All results

array_is_list() on a keyless tuple shape

Group: Cross-analyzer regressions · Category: regression · File: regressions_keyless_tuple_is_list.php

array{int, string} has implicit sequential integer keys 0 and 1, so it is always a list and array_is_list($t) is always true — the counterpart of the always-false optional-key cases. This records whether each tool treats the keyless tuple as a guaranteed list (reporting the check as redundantly true, or narrowing silently) and confirms consistency with the explicit-key list-ness case. Reference: phpstan#14939

Analyzer results

AnalyzerVersionResultDiagnostics
phan 6.0.10Phan 6.0.10 php-ast version 1.1.3 PHP version used to run Phan: 8.5.11 Pass

No diagnostics reported.

phpstan 2.3.1PHPStan - PHP Static Analysis Tool 2.3.1 Pass reported Lv.4+
regressions_keyless_tuple_is_list.php:22: Call to function array_is_list() with array{int, string} will always evaluate to true. [reported-from-level=4]
With strict-rules
regressions_keyless_tuple_is_list.php:22: Call to function array_is_list() with array{int, string} will always evaluate to true.
psalm 6.20.0Psalm 6.20.0@804f03c0c183d149fcd4b8c7c0c9b3fbf836d34c
next: 7.0.0-rc2
Pass (pzoom≠)
regressions_keyless_tuple_is_list.php:22: Type list{int, string} for $t is always list<mixed> [RedundantCondition]
pzoom (Psalm port)

No diagnostics from pzoom.

mago 1.57.0mago 1.57.0 Pass
regressions_keyless_tuple_is_list.php:22: Redundant type assertion: `$t` is already `array{0: int, 1: string}`. [redundant-type-comparison]
regressions_keyless_tuple_is_list.php:22: This condition (type `true`) will always evaluate to true. [redundant-condition]
mir 0.87.0mir 0.87.0 Pass
regressions_keyless_tuple_is_list.php:22: RedundantCondition: Condition is always false, so the then branch is never reached [MIR0400]
phpantom 0.11.1phpantom_lsp 0.11.1 Pass

No diagnostics reported.

intelephense 1.18.5intelephense 1.18.5 Pass

No diagnostics reported.

phpactor 2026.10.07.0Phpactor 2026.10.07.0 Pass

No diagnostics reported.

phpy 1.0.19409phpy 1.0.19409 Pass

No diagnostics reported.

qodana 262.10968.76PhpStorm 262.10968.76 Pass

No diagnostics reported.

noverify 0.5.5NoVerify, version 0.5.5: built on: 2025.04.22 14:36:46 OS: r-kuchinskas arm64 Commit: 4774b82f8adc53fbef38f95e97af4b953b4d1529 Pass
regressions_keyless_tuple_is_list.php:20: param $t miss matched with phpdoc type <<array{int, string}>> [funcParamTypeMissMatch]
steins 0.1.8steins 0.1.8 (2026-09-21 revision 76306a9) Pass

No diagnostics reported.

phpstan-strict 2.3.1PHPStan - PHP Static Analysis Tool 2.3.1 Pass
regressions_keyless_tuple_is_list.php:22: Call to function array_is_list() with array{int, string} will always evaluate to true.
psalm-next 7.0.0-rc2Psalm 7.0.0-rc2@20339e3fe5b8d03bcd8061030eb2a83ad50e5783 Pass
regressions_keyless_tuple_is_list.php:22: Type list{int, string} for $t is always list<mixed> [RedundantCondition]

Source

<?php

declare(strict_types=1);

namespace Conformance\Tests\RegressionsKeylessTupleIsList;

/**
 * `array_is_list()` on a keyless tuple shape.
 *
 * `array{int, string}` has implicit sequential integer keys 0 and 1, so it is always a
 * list and `array_is_list($t)` is always true — the counterpart of the always-false
 * optional-key cases. This records whether each tool treats the keyless tuple as a
 * guaranteed list (reporting the check as redundantly true, or narrowing silently) and
 * confirms consistency with the explicit-key list-ness case.
 *
 * Reference: https://github.com/phpstan/phpstan/discussions/14939
 */

/** @param array{int, string} $t */
function keylessTupleIsList(array $t): void // E<noverify>: NoVerify does not parse array shape syntax and flags the annotation itself
{
    if (array_is_list($t)) { // E<phpstan>: correctly always-true — keyless tuple is a list (function.alreadyNarrowedType) // E<phpstan-strict>: same always-true verdict // E<psalm>: RedundantCondition — always a list // E<mago>: redundant-condition — always true // E<mir>: RedundantCondition. Phan emits no redundancy note. Contrast with the always-false optional-key bug
        echo "always reached — a keyless tuple is a list\n";
    }
}

keylessTupleIsList([1, 'x']);