-
Notifications
You must be signed in to change notification settings - Fork 662
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
Broken assert for array and list - DocblockTypeContradiction #9037
Comments
I found these snippets: https://psalm.dev/r/ea9ecf75b9<?php
/**
*
* @param array<string, string>|list<string> $arg
* @return bool
*
* @psalm-assert array<string, string> $arg
* @psalm-assert-if-true =list<string> $arg
*/
function is_array_or_list( $arg ) {}
/**
* @var array<string, string>|list<string> $foo
*/
$bar = $foo;
/** @psalm-trace $bar */;
if ( $foo === array_values( $foo ) ) {
/** @psalm-trace $foo */;
}
if ( is_array_or_list( $foo ) === true ) {
/** @psalm-trace $foo */;
} else {
/** @psalm-trace $foo */;
}
|
Current situation seems correct In theory, this should work: https://psalm.dev/r/06c99cf8ac but it doesn't |
I found these snippets: https://psalm.dev/r/06c99cf8ac<?php
/**
*
* @param array<string, string>|list<string> $arg
* @return bool
*
* @psalm-assert-if-false =array<string, string> $arg
* @psalm-assert-if-true =list<string> $arg
*/
function is_array_or_list( $arg ) {}
/**
* @var array<string, string>|list<string> $foo
*/
$bar = $foo;
/** @psalm-trace $bar */;
if ( $foo === array_values( $foo ) ) {
/** @psalm-trace $foo */;
}
if ( is_array_or_list( $foo ) === true ) {
/** @psalm-trace $foo */;
} else {
/** @psalm-trace $foo */;
}
|
Which is fine, the issue is that it should report this for the assertion, not at every place this function is called? Afaik this was working fine in v4, this is a new issue in v5
Yes @psalm-assert-if-false and @psalm-assert-if-true should work when used together. |
I found these snippets: https://psalm.dev/r/06c99cf8ac<?php
/**
*
* @param array<string, string>|list<string> $arg
* @return bool
*
* @psalm-assert-if-false =array<string, string> $arg
* @psalm-assert-if-true =list<string> $arg
*/
function is_array_or_list( $arg ) {}
/**
* @var array<string, string>|list<string> $foo
*/
$bar = $foo;
/** @psalm-trace $bar */;
if ( $foo === array_values( $foo ) ) {
/** @psalm-trace $foo */;
}
if ( is_array_or_list( $foo ) === true ) {
/** @psalm-trace $foo */;
} else {
/** @psalm-trace $foo */;
}
|
As far as I know, contradiction in assertions were always reported where the contradiction is processed, on the method call. |
I didn't have this issue in v4 though (this same code passed in v4 without any errors, as I am just revisiting a file that was last modified in September and passed without errors back then) |
Works fine for any types e.g. int|list https://psalm.dev/r/4733a4c121 except for array|list since they are combined into 1 type - which is where the use of @psalm-assert-if-false combined with @psalm-assert-if-true would come in handy |
I found these snippets: https://psalm.dev/r/4733a4c121<?php
/**
*
* @param int|list<string> $arg
* @return bool
*
* @psalm-assert-if-true list<string> $arg
*/
function is_array_or_int( $arg ) {}
/**
* @var int|list<string> $foo
*/
$bar = $foo;
if ( is_array_or_int( $foo ) ) {
/** @psalm-trace $foo */;
} else {
/** @psalm-trace $foo */;
}
|
https://psalm.dev/r/ea9ecf75b9
As we see in line 20, psalm correctly infers that $foo can be type list when checking with array_values
When using a custom assert function, it correctly asserts it, but reports a false positive
DocblockTypeContradiction
on the if condition in line 23What actually happens here is, that it assumes that @psalm-assert type
array<string, string>
does not containlist<string>
which is correct - however why does it report this as a DocblockTypeContradiction in the place where the function is called?How can I assert
if true => list<string>
,if false => array<string, string>
?The text was updated successfully, but these errors were encountered: