← All results

array-key

Group: Advanced PHPDoc types · Category: ecosystem · File: phpdoc_advanced_fallback_array_key.php

array-key is the union of the types PHP accepts as an array key, int|string. Unlike the other pseudo-types in this group it refines no single native type: both int and string satisfy it, while an array-key value satisfies neither int nor string on its own. Analyzers that model it reject a value PHP cannot use as a key; others fall back to mixed and accept everything. The reverse direction separates the analyzers further. PHPStan resolves the keyword to a *benevolent* union, which is deliberately accepted wherever either member is expected, so passing an array-key to a native string parameter stays silent there. Analyzers that resolve it to an ordinary int|string — or to a dedicated array-key atom — report the half of the union that does not fit. References: - PHPStan TypeNodeResolver array-key resolves to BenevolentUnionType(int|string) - Psalm docs, Type syntax / Scalar types: array-key

Analyzer results

AnalyzerVersionResultDiagnostics
phan 6.0.7Phan 6.0.7 php-ast version 1.1.3 PHP version used to run Phan: 8.5.9 Partly enforced (3/5)
phpdoc_advanced_fallback_array_key.php:58: Argument 1 ($value) is 1.5 of type float (value: 1.5) but \Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsArrayKey() takes int|string (no real type) defined at /Users/megurine/repo/php/php-typing-conformance/conformance/tests/phpdoc_advanced_fallback_array_key.php:48 (the inferred real argument type has nothing in common with the parameter's phpdoc type) [PhanTypeMismatchArgumentProbablyReal]
phpdoc_advanced_fallback_array_key.php:59: Argument 1 ($value) is true of type true but \Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsArrayKey() takes int|string (no real type) defined at /Users/megurine/repo/php/php-typing-conformance/conformance/tests/phpdoc_advanced_fallback_array_key.php:48 (the inferred real argument type has nothing in common with the parameter's phpdoc type) [PhanTypeMismatchArgumentProbablyReal]
phpdoc_advanced_fallback_array_key.php:60: Argument 1 ($value) is null of type null but \Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsArrayKey() takes int|string (no real type) defined at /Users/megurine/repo/php/php-typing-conformance/conformance/tests/phpdoc_advanced_fallback_array_key.php:48 (the inferred real argument type has nothing in common with the parameter's phpdoc type) [PhanTypeMismatchArgumentProbablyReal]
  • Recognition: spelling resolved
  • Enforcement: 3/5 of the expected violations reported
phpstan 2.2.8PHPStan - PHP Static Analysis Tool 2.2.8 Partly enforced (3/5) reported Lv.5+
phpdoc_advanced_fallback_array_key.php:58: Parameter #1 $value of function Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsArrayKey expects (int|string), float given. [identifier=argument.type] [reported-from-level=5]
phpdoc_advanced_fallback_array_key.php:59: Parameter #1 $value of function Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsArrayKey expects (int|string), true given. [identifier=argument.type] [reported-from-level=5]
phpdoc_advanced_fallback_array_key.php:60: Parameter #1 $value of function Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsArrayKey expects (int|string), null given. [identifier=argument.type] [reported-from-level=5]
With strict-rules
phpdoc_advanced_fallback_array_key.php:58: Parameter #1 $value of function Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsArrayKey expects (int|string), float given. [identifier=argument.type]
phpdoc_advanced_fallback_array_key.php:59: Parameter #1 $value of function Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsArrayKey expects (int|string), true given. [identifier=argument.type]
phpdoc_advanced_fallback_array_key.php:60: Parameter #1 $value of function Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsArrayKey expects (int|string), null given. [identifier=argument.type]
  • Recognition: spelling resolved
  • Enforcement: 3/5 of the expected violations reported
psalm 6.16.1Psalm 6.16.1@f1f5de594dc76faf8784e02d3dc4716c91c6f6ac
next: 7.0.0-beta19
Enforced
phpdoc_advanced_fallback_array_key.php:58: Argument 1 of Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsArrayKey expects array-key, but float(1.5) provided [InvalidArgument]
phpdoc_advanced_fallback_array_key.php:59: Argument 1 of Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsArrayKey expects array-key, but true provided [InvalidArgument]
phpdoc_advanced_fallback_array_key.php:60: Argument 1 of Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsArrayKey cannot be null, null value provided to parameter with type array-key [NullArgument]
phpdoc_advanced_fallback_array_key.php:65: Argument 1 of Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsInt expects int, but parent type array-key provided [MixedArgumentTypeCoercion]
phpdoc_advanced_fallback_array_key.php:66: Argument 1 of Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsString expects string, but parent type array-key provided [MixedArgumentTypeCoercion]
  • Recognition: spelling resolved
  • Enforcement: 5/5 of the expected violations reported
mago 1.46.0mago 1.46.0 Enforced
phpdoc_advanced_fallback_array_key.php:58: Invalid argument type for argument #1 of `Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsArrayKey`: expected `array-key`, but found `float(1.5)`. [invalid-argument]
phpdoc_advanced_fallback_array_key.php:59: Invalid argument type for argument #1 of `Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsArrayKey`: expected `array-key`, but found `true`. [invalid-argument]
phpdoc_advanced_fallback_array_key.php:60: Argument #1 of function `Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsArrayKey` is `null`, but parameter type `array-key` does not accept it. [null-argument]
phpdoc_advanced_fallback_array_key.php:65: Argument type mismatch for argument #1 of `Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsInt`: expected `int`, but provided type `array-key` is less specific. [less-specific-argument]
phpdoc_advanced_fallback_array_key.php:66: Argument type mismatch for argument #1 of `Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsString`: expected `string`, but provided type `array-key` is less specific. [less-specific-argument]
  • Recognition: spelling resolved
  • Enforcement: 5/5 of the expected violations reported
mir 0.70.1mir 0.70.1 Partly enforced (3/5)
phpdoc_advanced_fallback_array_key.php:58: InvalidArgument: Argument $value of acceptsArrayKey() expects 'int|string', got '1.5' [MIR0201]
phpdoc_advanced_fallback_array_key.php:59: InvalidArgument: Argument $value of acceptsArrayKey() expects 'int|string', got 'true' [MIR0201]
phpdoc_advanced_fallback_array_key.php:60: NullArgument: Argument $value of acceptsArrayKey() cannot be null [MIR0100]
  • Recognition: spelling resolved
  • Enforcement: 3/5 of the expected violations reported
phpantom 0.9.0phpantom_lsp 0.9.0 Enforced
phpdoc_advanced_fallback_array_key.php:58: Argument 1 ($value) expects array-key, got 1.5 [type_mismatch_argument]
phpdoc_advanced_fallback_array_key.php:59: Argument 1 ($value) expects array-key, got bool [type_mismatch_argument]
phpdoc_advanced_fallback_array_key.php:60: Argument 1 ($value) expects array-key, got null [type_mismatch_argument]
phpdoc_advanced_fallback_array_key.php:65: Argument 1 ($value) expects int, got array-key [type_mismatch_argument]
phpdoc_advanced_fallback_array_key.php:66: Argument 1 ($value) expects string, got array-key [type_mismatch_argument]
  • Recognition: spelling resolved
  • Enforcement: 5/5 of the expected violations reported
intelephense 1.18.5intelephense 1.18.5 Partly enforced (2/5)
phpdoc_advanced_fallback_array_key.php:65: Expected type 'int'. Found 'string|int'. [P1006]
phpdoc_advanced_fallback_array_key.php:66: Expected type 'string'. Found 'string|int'. [P1006]
  • Recognition: spelling resolved
  • Enforcement: 2/5 of the expected violations reported
phpy 0.2.0phpy 0.2.0 Partly enforced (3/5)
phpdoc_advanced_fallback_array_key.php:58: Argument '1' passed to Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsArrayKey() is expected to be of type int|string, float given
phpdoc_advanced_fallback_array_key.php:59: Argument '1' passed to Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsArrayKey() is expected to be of type int|string, bool given
phpdoc_advanced_fallback_array_key.php:60: Argument '1' passed to Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsArrayKey() is expected to be of type int|string, null given
  • Recognition: spelling resolved
  • Enforcement: 3/5 of the expected violations reported
qodana 262.8665.325Qodana 262.8665.325 Partly enforced (2/5)
phpdoc_advanced_fallback_array_key.php:58: Parameter '1.5' type is not compatible with declaration when using strict type matching [PhpParamsInspection]
phpdoc_advanced_fallback_array_key.php:59: Parameter 'true' type is not compatible with declaration when using strict type matching [PhpParamsInspection]
  • Recognition: spelling resolved
  • Enforcement: 2/5 of the expected violations reported
noverify 0.5.5NoVerify, version 0.5.5: built on: 2025.04.22 14:36:46 OS: r-kuchinskas arm64 Commit: 4774b82f8adc53fbef38f95e97af4b953b4d1529 Partly enforced (2/5)
phpdoc_advanced_fallback_array_key.php:59: potentially not safe access in parameter value of function Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsArrayKey [notSafeCall]
phpdoc_advanced_fallback_array_key.php:60: null passed to non-nullable parameter value in function Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsArrayKey [notNullSafetyFunctionArgumentConstFetch]
  • Recognition: spelling resolved
  • Enforcement: 2/5 of the expected violations reported
steins 0.1.5steins 0.1.5 (2026-08-12 revision 39b4cc1) Partly enforced (3/5)
phpdoc_advanced_fallback_array_key.php:58: argument 1.5 to acceptsArrayKey() violates declared @param array-key $value — declared contract violation [phpdoc.param-mismatch]
phpdoc_advanced_fallback_array_key.php:59: argument true to acceptsArrayKey() violates declared @param array-key $value — declared contract violation [phpdoc.param-mismatch]
phpdoc_advanced_fallback_array_key.php:60: argument null to acceptsArrayKey() violates declared @param array-key $value — declared contract violation [phpdoc.param-mismatch]
  • Recognition: spelling resolved
  • Enforcement: 3/5 of the expected violations reported

Notes: The 2 residual lines (65-66: forwarding returnsArrayKey()'s declared int|string return straight into acceptsInt()/acceptsString()) are an honest gap, not a Maybe: nothing in steins-infer propagates a callee's declared @return contract into the caller's argument-fact lane for a bare call-expression argument, so no verdict at all is computed there. The 3 direct-value lines (58-60) do fire correctly.

phpstan-strict 2.2.8PHPStan - PHP Static Analysis Tool 2.2.8 Partly enforced (3/5)
phpdoc_advanced_fallback_array_key.php:58: Parameter #1 $value of function Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsArrayKey expects (int|string), float given. [identifier=argument.type]
phpdoc_advanced_fallback_array_key.php:59: Parameter #1 $value of function Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsArrayKey expects (int|string), true given. [identifier=argument.type]
phpdoc_advanced_fallback_array_key.php:60: Parameter #1 $value of function Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsArrayKey expects (int|string), null given. [identifier=argument.type]
  • Recognition: spelling resolved
  • Enforcement: 3/5 of the expected violations reported
psalm-next 7.0.0-beta19Psalm 7.0.0-beta19@7e751c06a756fa64dc4c759c09fe4a173afcb433 Enforced
phpdoc_advanced_fallback_array_key.php:58: Argument 1 of Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsArrayKey expects array-key, but float(1.5) provided [InvalidArgument]
phpdoc_advanced_fallback_array_key.php:59: Argument 1 of Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsArrayKey expects array-key, but true provided [InvalidArgument]
phpdoc_advanced_fallback_array_key.php:60: Argument 1 of Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsArrayKey cannot be null, null value provided to parameter with type array-key [NullArgument]
phpdoc_advanced_fallback_array_key.php:65: Argument 1 of Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsInt expects int, but parent type array-key provided [MixedArgumentTypeCoercion]
phpdoc_advanced_fallback_array_key.php:66: Argument 1 of Conformance\Tests\PhpdocAdvancedFallbackArrayKey\acceptsString expects string, but parent type array-key provided [MixedArgumentTypeCoercion]
  • Recognition: spelling resolved
  • Enforcement: 5/5 of the expected violations reported

Source

<?php

declare(strict_types=1);

namespace Conformance\Tests\PhpdocAdvancedFallbackArrayKey;

/**
 * `array-key`
 *
 * `array-key` is the union of the types PHP accepts as an array key,
 * `int|string`. Unlike the other pseudo-types in this group it refines no
 * single native type: both `int` and `string` satisfy it, while an `array-key`
 * value satisfies neither `int` nor `string` on its own. Analyzers that model
 * it reject a value PHP cannot use as a key; others fall back to `mixed` and
 * accept everything.
 *
 * The reverse direction separates the analyzers further. PHPStan resolves the
 * keyword to a *benevolent* union, which is deliberately accepted wherever
 * either member is expected, so passing an `array-key` to a native `string`
 * parameter stays silent there. Analyzers that resolve it to an ordinary
 * `int|string` — or to a dedicated array-key atom — report the half of the
 * union that does not fit.
 *
 * References:
 * - PHPStan TypeNodeResolver `array-key` resolves to BenevolentUnionType(int|string)
 * - Psalm docs, Type syntax / Scalar types: `array-key`
 */

/**
 * @return array-key
 */
function returnsArrayKey() // T: array-key
{
    return \random_int(0, 1) === 1 ? 1 : 'key'; // V
}

function acceptsInt(int $value): void
{
}

function acceptsString(string $value): void
{
}

/**
 * @param array-key $value
 */
function acceptsArrayKey($value): void // T: array-key
{
}

// Both members of the union satisfy the parameter.
acceptsArrayKey(1); // V
acceptsArrayKey('key'); // V

// Values PHP cannot use as an array key: analyzers that model `array-key`
// reject them, others fall back to `mixed` and accept them.
acceptsArrayKey(1.5); // E?: a float is not an array-key (int|string)
acceptsArrayKey(true); // E?: a bool is not an array-key (int|string)
acceptsArrayKey(null); // E?: null is not an array-key (int|string)

// The reverse direction: an `array-key` is not narrowed to either member, so a
// parameter that wants only one of them is not satisfied. PHPStan's benevolent
// union stays silent here by design.
acceptsInt(returnsArrayKey()); // E?: an array-key may be a string
acceptsString(returnsArrayKey()); // E?: an array-key may be an int