| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
PHP casts a decimal-integer string array key ("123") to int, so
`array_key_first([$string => null])` is not necessarily a string. PHPStan
inferred `string` for it and reported `is_int()` on the result as always false.
UnsafeArrayStringKeyCastingTraverser already modelled that cast, but only for
the key type an array *has* — a type that also decides how the array describes
itself and what it accepts, which is why only
`reportUnsafeArrayStringKeyCasting: detect` widens it. Widening it with the
toggle off turns `array<string, X>` into `array<X>` everywhere.
castReadKeyType() is the second entry point, for a key that leaves the array as
a value of its own. With the toggle off it widens `string` to the benevolent
`(int|string)`, so neither branch reports anything; `detect` and `prevent` keep
the types they have today. unionWithReadKeyType() adds the `null` an empty array
gives back without losing the benevolence on the way.
The remaining accessors follow in the next commit.
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
array_rand() collapsed the array's key type into int, string or int|string, and
returned `array<int, key>` whenever $num was more than one. Hand back the key
type itself, and build a tuple when $num is a known constant:
array_rand(['a' => 1, 'b' => 2]) 'a'|'b' (was string)
array_rand($list) int<0, max> (was int)
array_rand($shape, 2) array{key, key} (was array<int, key>)
array_rand($shape, $atLeastTwo) non-empty-list<key>
An array comes back only when $num is at least 2, since a single pick returns
the key on its own, so the list is non-empty in every branch that produces one.
KEY_COUNT_LIMIT caps the tuple at 100 elements, past which
ConstantArrayTypeBuilder would degrade the shape anyway.
The keys run through castReadKeyType(), so `array<string, X>` gives
`(int|string)` rather than a certain `string`.
array_rand([]) returns never now, which is what PHP 8 does (ValueError). That
also makes everything after the call unreachable, so the two calls in
data/array_rand.php moved into separate functions to keep their diagnostics.
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
| Back | FazBrowse Home | New Git URL |
Builds on #6222. Its first commit is cherry-picked here so this branch analyses on its own; I will rebase it away once it lands.
Problem
array_rand() threw away what it knew about the keys. It collapsed the key type into int, string or int|string, and returned array<int, key> whenever $num was more than one:
Change
Hand back the key type itself, and build a tuple when $num is a known constant:
An array comes back only when $num is at least 2, since a single pick returns the key on its own. That makes the list non-empty in every branch that produces one.
KEY_COUNT_LIMIT caps the tuple at 100 elements. Past that ConstantArrayTypeBuilder would degrade the shape anyway.
The keys run through castReadKeyType() from #6222, so array<string, X> gives (int|string) rather than a certain string.
array_rand([]) returns never now
array_rand([]) throws a ValueError on PHP 8, so never is the honest type. It also makes everything after the call unreachable, which cost the second call in data/array_rand.php its diagnostics. The two calls sit in separate functions now.
Tests
nsrt/array-rand.php is new. nsrt/array-functions.php and data/bug-9803.php gain precision, and two rule tests carry the new types in their messages.