-
Notifications
You must be signed in to change notification settings - Fork 677
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
IfAnalyzer incorrectly updates outer scope #9433
Comments
I found these snippets: https://psalm.dev/r/461cbad1b2<?php
/**
* @param list<string> $list
*/
function modify(array &$list, int $offset, string $val): void
{
$list[$offset] = $val;
}
https://psalm.dev/r/dd0484a239<?php
/**
* @param list<string> $list
*/
function modify(array &$list, int $offset, string $val): void
{
if(isset($list[$offset])) { }
$list[$offset] = $val;
}
|
Handling list assignments is more interesting, just compare these two examples (and the very first example without https://psalm.dev/r/7310523657 https://psalm.dev/r/14d1091480 The difference between above two is |
I found these snippets: https://psalm.dev/r/7310523657<?php
/**
* @param list<string> $list
*/
function modify(array &$list, int $offset, string $val): void
{
if(isset($list[$offset])) {
$list[$offset] = $val;
}
}
https://psalm.dev/r/14d1091480<?php
/**
* @param list<string> $list
*/
function modify(array &$list, int $offset, string $val): void
{
if(!isset($list[$offset])) {
$list[$offset] = $val;
}
}
|
Note: you can use @psalm-trace to see what Psalm think of the types at different places: So the difference there is Psalm seems to be convinced that the type is still a list but only after isset() is checked. According to your other snippets, it seems it doesn't even matter how isset was checked (checking the existence or absence do the same) My guess is that there's a flaw in the way Psalm adds a dynamic offset to an existing list. It may be hard to solve, sometimes, Psalm makes some simplifications in order to allow a specific code construct but this creates edge cases like this |
I found these snippets: https://psalm.dev/r/c3879d8df6<?php
/**
* @param list<string> $list
*/
function modify(array &$list, int $offset, string $val): void
{
if(isset($list[$offset])) {
/** @psalm-trace $list */;
}
/** @psalm-trace $list */;
$list[$offset] = $val;
/** @psalm-trace $list */;
}
https://psalm.dev/r/f7570574b5<?php
/**
* @param list<string> $list
*/
function modify(array &$list, int $offset, string $val): void
{
/** @psalm-trace $list */;
$list[$offset] = $val;
/** @psalm-trace $list */;
}
|
For the example with
|
yeah but potentially, you want this context to change (for example if you change the variable inside of a branch of the if or if one of the branch returns or something like that) |
sure, but it should be done correctly, currently it's buggy, the problem appears to be in another place, so that 289 line is only a starting point for deeper search. Anyway, the fix is on my way. |
possibly related or same issue: #9412 |
Yes, it's related. |
Consider this example, which correctly reports ReferenceConstraintViolation (dumb inserts into
list
may introduce discontinuites in indexint turninglist
intoarray
):https://psalm.dev/r/461cbad1b2
Now, adding dummy
if(isset(...)){}
, which has no chance to change flow of control, results with false negative (error disappears):https://psalm.dev/r/dd0484a239
The text was updated successfully, but these errors were encountered: