Skip to content

Fix phpstan/phpstan#14223: Variable $ in empty() always exists and is not falsy.#5124

Merged
VincentLanglet merged 1 commit intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-42f264f
Mar 3, 2026
Merged

Fix phpstan/phpstan#14223: Variable $ in empty() always exists and is not falsy.#5124
VincentLanglet merged 1 commit intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-42f264f

Conversation

@phpstan-bot
Copy link
Collaborator

Summary

array_count_values() on a possibly-empty input array was incorrectly returning non-empty-array<..., int<1, max>> instead of array<..., int<1, max>>. This caused a false positive empty.variable error when using empty() on the result, since PHPStan believed the value was always non-falsy.

Changes

  • Modified src/Type/Php/ArrayCountValuesDynamicReturnTypeExtension.php to check $inputType->isIterableAtLeastOnce()->yes() before adding NonEmptyArrayType to the result
  • Updated assertion in tests/PHPStan/Analyser/nsrt/array-count-values.php for the returnsStringOrObjectArray() case which returns a possibly-empty array
  • Added regression test in tests/PHPStan/Analyser/nsrt/bug-14223.php

Root cause

ArrayCountValuesDynamicReturnTypeExtension unconditionally wrapped every output type in an IntersectionType with NonEmptyArrayType. This was incorrect because when the input array could be empty (e.g., list<string>), array_count_values([]) returns []. The fix checks whether the input type is definitely non-empty (isIterableAtLeastOnce()->yes()) before adding the NonEmptyArrayType accessory type.

Test

The regression test tests/PHPStan/Analyser/nsrt/bug-14223.php verifies:

  • array_count_values() on list<string> (possibly empty) returns array<string, int<1, max>> (not non-empty-array)
  • array_count_values() on non-empty-list<string> (definitely non-empty) still returns non-empty-array<string, int<1, max>>

Fixes phpstan/phpstan#14223

… should not return non-empty-array

- ArrayCountValuesDynamicReturnTypeExtension always added NonEmptyArrayType to the result, even when the input array could be empty
- Now checks $inputType->isIterableAtLeastOnce() before marking the output as non-empty
- Updated existing test assertion for returnsStringOrObjectArray() which returns a possibly-empty array
- New regression test in tests/PHPStan/Analyser/nsrt/bug-14223.php
@staabm
Copy link
Contributor

staabm commented Mar 3, 2026

@VincentLanglet please double check the issue-bot results on issue 14107

@VincentLanglet
Copy link
Contributor

@VincentLanglet please double check the issue-bot results on issue 14107

Seems ok to me

@VincentLanglet VincentLanglet merged commit f08de42 into phpstan:2.1.x Mar 3, 2026
634 of 647 checks passed
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