psalm: Incorrect RedundantCast and lack of MixedArgumentTypeCoercion with array-key type
I have an array which contains both string and integer keys. After upgrading from Psalm 3.14.2 to 4.3.1, I ran into a couple different issues with this code:
- When looping over the array in the constructor method, Psalm fails to show a
MixedArgumentTypeCoercion
error when passing the array key to a function that requires a string. However, Psalm correctly shows this error when the same code is placed in another function called by the constructor. - In the function called by the constructor, even though Psalm correctly shows an error when directly passing the array key to a function expecting an int, if I cast the array key to a string to avoid a runtime TypeError, Psalm incorrectly shows a
RedundantCast
error.
<?php
declare(strict_types=1);
class Thing
{
public function __construct(
public string $name,
public string $value,
) {}
}
new Foo([
new Thing('foo', 'bar'),
// Foo::__construct will cause the string '123' to end up as an int array key
new Thing('123', 'baz'),
]);
class Foo
{
/**
* @var array<mixed, string>
*/
public array $map;
/**
* @param Thing[] $things
*/
public function __construct(array $things)
{
$this->map = [];
foreach ($things as $thing) {
$this->map[$thing->name] = $thing->value;
}
// map may now contain some string keys and some int keys
foreach ($this->map as $key => $value) {
// $key may be an int, but Psalm fails to produce the error it does inside useMap()
echo strlen($key);
}
$this->useMap();
}
public function useMap(): void
{
foreach ($this->map as $key => $value) {
// this line correctly causes an error
echo strlen($key); // MixedArgumentTypeCoercion: Argument 1 of strlen expects string, parent type of array-key provided
// this line incorrectly says the cast is redundant
echo strlen((string) $key); // RedundantCast: Redundant cast to string
}
}
}
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 15 (3 by maintainers)
Commits related to this issue
- Fix #4778 - remove already-initialized properties when checking initialisation — committed to danog/psalm by muglug 4 years ago
I proposed something to handle this issue a few month ago: https://github.com/vimeo/psalm/pull/4237.
However, this is something that will probably have a lot of false positives (almost every string array-key is potentially problematic) for only a few actual bug caught
Everything Psalm is saying here is correct.