Add generic type signatures for array_first, array_last, array_any and array_all#11883
Add generic type signatures for array_first, array_last, array_any and array_all#11883delolmo wants to merge 3 commits into
Conversation
|
Heads up for reviewers: the failing |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 375524f. Configure here.
Summary
PHP 8.4's
array_any/array_alland PHP 8.5'sarray_first/array_lastare currently only described by the autogenerated CallMap, which gives them non-generic signatures:array_first(array): mixedandarray_last(array): mixed— the element type is lost, callers getmixed.array_any(array, callable): boolandarray_all(array, callable): bool— the callback parameters are untypedcallable, so the value/key types are not checked inside the predicate.This adds templated stubs to
stubs/CoreGenericFunctions.phpstub, directly mirroring the existingarray_key_first/array_key_lastentries that sit a few lines above:array_first/array_lastreturnvalue-of<TArray>, with the same emptiness-aware conditional asarray_key_first(nullfor a statically-empty array, the value type for anon-empty-array, otherwisevalue-of<TArray>|null).array_any/array_allkeep theirboolreturn but gain a typedcallable(TValue, TKey): boolpredicate so the callback body is checked against the array's value and key types. They are marked@psalm-pure: unlikeusort/uasort(which mutate their by-reference array), these functions do not mutate, so the call is pure when given a pure callback and Psalm propagates the callback's purity. This also matches Psalm's own source, which callsarray_anyfrom mutation-free contexts (e.g.Type\Atomic).Tests
Adds cases to
tests/ArrayFunctionCallTest.phpcovering the general,non-empty-arrayand empty-array branches forarray_first/array_last, plus typed-callbackboolresults forarray_any/array_all.Note
array_first/array_last/array_any/array_allalready exist in the version CallMaps (CallMap_84/CallMap_85); placing the generic signatures inCoreGenericFunctions.phpstubmatches wherearray_key_first/array_key_lastalready live so the improved types apply regardless of the PHP version Psalm itself runs on. Happy to move them behind version gating if you'd prefer.