Skip to content

Fix phpstan/phpstan#14037: array_splice resets int keys of the input array#5139

Merged
VincentLanglet merged 6 commits intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-npoxue5
Mar 8, 2026
Merged

Fix phpstan/phpstan#14037: array_splice resets int keys of the input array#5139
VincentLanglet merged 6 commits intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-npoxue5

Conversation

@phpstan-bot
Copy link
Collaborator

@phpstan-bot phpstan-bot commented Mar 7, 2026

Summary

array_splice resets integer keys of the input array to sequential 0, 1, 2, ... while preserving string keys. PHPStan correctly handled this for constant arrays but not for general array types like array<10|20|30|'a', mixed>, which should become array<'a'|int, mixed> after splicing.

Changes

  • Modified ArrayType::spliceArray() in src/Type/ArrayType.php to generalize integer key types to int using TypeTraverser, since array_splice re-indexes integer keys
  • Added regression test in tests/PHPStan/Analyser/nsrt/bug-14037.php

Root cause

ArrayType::spliceArray() used $this->getIterableKeyType() directly as the key type for the resulting array. This preserved specific integer constant types (like 10|20|30) verbatim, but PHP's array_splice re-indexes all integer keys to sequential integers starting from 0. The fix uses TypeTraverser to walk the key type and replace any integer type with a generic IntegerType, while leaving string key types unchanged.

Test

The regression test verifies that array<10|20|30|'a', mixed> becomes array<'a'|int, mixed> after array_splice($a, 0, 0).

Fixes phpstan/phpstan#14037

Closes #4844

VincentLanglet and others added 4 commits March 7, 2026 10:52
- Generalize specific integer key types (e.g. 10|20|30) to int in ArrayType::spliceArray()
- Uses TypeTraverser to only affect integer parts of union key types, preserving string keys
- New regression test in tests/PHPStan/Analyser/nsrt/bug-14037.php
- The root cause was that ArrayType::spliceArray() preserved the original key type verbatim, but PHP's array_splice re-indexes integer keys to 0, 1, 2, ...
@VincentLanglet VincentLanglet requested a review from staabm March 7, 2026 12:14
Comment on lines +390 to +391
/** @var array<string, string> $arr */
$arr;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would use a @param type, so we don't unnecessarily promoted inline-phpdocs

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated

use function PHPStan\Testing\assertType;

/**
* @param array<10|20|30|'a', mixed> $a
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also add a test for integer-range

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@VincentLanglet VincentLanglet merged commit 869ddb3 into phpstan:2.1.x Mar 8, 2026
636 of 648 checks passed
@VincentLanglet VincentLanglet deleted the create-pull-request/patch-npoxue5 branch March 8, 2026 12:16
uekann pushed a commit to uekann/phpstan-src that referenced this pull request Mar 9, 2026
…t array (phpstan#5139)

Co-authored-by: VincentLanglet <[email protected]>
Co-authored-by: Vincent Langlet <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants