New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
False positive TooFewArguments
with non-empty-list
and spread operator
#7603
Comments
I found these snippets: https://psalm.dev/r/09a02c2b5f<?php
function func(string $item1, string $item2, string ...$otherItems): array {
return [$item1, $item2, ...$otherItems];
}
/**
* @var non-empty-list<string> $existingItems
* @var string $newItem
*/
func(...[...$existingItems, $newItem]);
https://psalm.dev/r/5f60f9ef1b<?php
function func(string $item1, string $item2, string ...$otherItems): array {
return [$item1, $item2, ...$otherItems];
}
$existingItems = ['item1'];
$newItem = 'item2';
func(...[...$existingItems, $newItem]);
|
Psalm doesn't have a concept of 'list with at least N elements, N > 1'. So inner splat results in |
I found these snippets: https://psalm.dev/r/3cdda0aa21<?php
function func(string $item1, string $item2, string ...$otherItems): array {
return [$item1, $item2, ...$otherItems];
}
/**
* @var non-empty-list<string> $existingItems
* @var string $newItem
*/
$args = [...$existingItems, $newItem];
/** @psalm-trace $args */;
func(...$args);
|
Basically, we can't do much here given the confines of the type system we currently have in Psalm. |
This could become an improvement though. There are already places in Psalm's code where we check for min_count (for example, TypeCombiner). The goal is to check a combined array is never empty. It could make sense to store min_count on non-empty-arrays / list for this. We already have assertions for that and everything... |
Thanks, I see that now. Before 4.19 there was no error reported, so I thought psalm was able to track the min size of the list. |
I found these snippets: https://psalm.dev/r/3cdda0aa21<?php
function func(string $item1, string $item2, string ...$otherItems): array {
return [$item1, $item2, ...$otherItems];
}
/**
* @var non-empty-list<string> $existingItems
* @var string $newItem
*/
$args = [...$existingItems, $newItem];
/** @psalm-trace $args */;
func(...$args);
|
I completely reworked this check here: #7348 It was unable to check for named arguments and it forced me to start from scratch. I may have missed some checks Psalm was making in order to reduce the amount of false positives though. For example, I could add something in here that prevent emitting this issue when we have a non-empty-array with no known count. This would probably reduce false positives (as well as removing some possible bug warning for unckecked arrays...). What do you think @dsech @weirdan ? Maybe we should only do that when we have a variadic argument on the end? (For all other cases, I think we can expect a count() === X to be made before the call...) |
Ideally I'd love to see psalm keep track of min and max size of the array/list (obviously). Personally I'm good with just leaving a |
We can express the unbounded list with N guaranteed elements in Psalm 5 as |
I found these snippets: https://psalm.dev/r/80dd0babf0<?php
function func(string $item1, string $item2, string ...$otherItems): array {
return [$item1, $item2, ...$otherItems];
}
/**
* @var non-empty-list<string> $existingItems
* @var string $newItem
*/
$z = [...$existingItems, $newItem];
assert(count($z) >= 2);
/** @psalm-trace $z */;
func(...$z);
|
It looks like this is fixed, because the But (not sure if relevant to this issue) the size >= 2 information is lost after calling |
I found these snippets: https://psalm.dev/r/80dd0babf0<?php
function func(string $item1, string $item2, string ...$otherItems): array {
return [$item1, $item2, ...$otherItems];
}
/**
* @var non-empty-list<string> $existingItems
* @var string $newItem
*/
$z = [...$existingItems, $newItem];
assert(count($z) >= 2);
/** @psalm-trace $z */;
func(...$z);
https://psalm.dev/r/18a8f67489<?php
function func(string $item1, string $item2, string ...$otherItems): array {
return [$item1, $item2, ...$otherItems];
}
/**
* @var non-empty-list<string> $existingItems
* @var string $newItem
*/
$z = [...$existingItems, $newItem];
/** @psalm-trace $z */;
func(...$z);
/** @psalm-trace $z */
https://psalm.dev/r/90e8d5a001<?php
function func(string $item1, string $item2, string ...$otherItems): array {
return [$item1, $item2, ...$otherItems];
}
/**
* @var non-empty-list<string> $existingItems
* @var string $newItem
*/
$z = [...$existingItems, $newItem];
/** @psalm-trace $z */
func(...$z);
|
https://psalm.dev/r/09a02c2b5f
The issue exists in versions >=4.19.0
Looks to be related to the
non-empty-list
typehint, because there is no error reported if the variables are declared: https://psalm.dev/r/5f60f9ef1bThe text was updated successfully, but these errors were encountered: