psalm icon indicating copy to clipboard operation
psalm copied to clipboard

UnusedVariable false positive with thrown and caught exceptions

Open Daeroni opened this issue 4 years ago • 10 comments

If a variable is modified just before an exception is thrown, and then caught in the same context and the variable used, psalm emits an UnusedVariable issue.

https://psalm.dev/r/95027a9b22 https://3v4l.org/9UkSq

Daeroni avatar May 02 '21 15:05 Daeroni

I found these snippets:

https://psalm.dev/r/95027a9b22
<?php

function test(bool $b): string {
	$test = 'test';

	try {
    	if ($b) {
        	$test .= ' true';
        	throw new Exception;
    	}
	} catch (Exception $e) {
	}

    return $test . "\n";
}

print test(false);
print test(true);
Psalm output (using commit eb71506):

INFO: UnusedVariable - 8:10 - $test is never referenced or the value is not used

psalm-github-bot[bot] avatar May 02 '21 15:05 psalm-github-bot[bot]

Also a different false-positive for type assignment (because unused variable tracking uses the same pathways): https://psalm.dev/r/621191710b

muglug avatar May 02 '21 16:05 muglug

I found these snippets:

https://psalm.dev/r/621191710b
<?php

function test(): void {
	$did_throw = false;

	try {
    	if (rand(0, 1)) {
        	$did_throw = true;
        	throw new Exception;
    	}
	} catch (Exception $e) {
	}
    
    if ($did_throw) {}
}
Psalm output (using commit eb71506):

ERROR: TypeDoesNotContainType - 14:9 - if (false) is impossible

INFO: UnusedVariable - 8:10 - $did_throw is never referenced or the value is not used

psalm-github-bot[bot] avatar May 02 '21 16:05 psalm-github-bot[bot]

I also ran in this issue, and the issue went away after I downgraded all the way to 4.6.4

tostiheld avatar May 23 '21 17:05 tostiheld

I also have a same sort of problem. In the catch I call the same function. https://psalm.dev/r/43e4ab49f4

thepercival avatar Sep 18 '21 06:09 thepercival

I found these snippets:

https://psalm.dev/r/43e4ab49f4
<?php

function getData(int $nrOfRetries = 0): void
{
    try {
        if( $nrOfRetries < 10 ) {                
            throw new \Exception('do another iteration', E_ERROR);
        }
    } catch (\Exception $e) {
        getData(++$nrOfRetries);
    }
}
Psalm output (using commit 37362b3):

INFO: UnusedVariable - 10:19 - $nrOfRetries is never referenced or the value is not used

psalm-github-bot[bot] avatar Sep 18 '21 06:09 psalm-github-bot[bot]

@thepercival your case seems discutable because $i++ is equivalent to $i = $i + 1, so it makes the addition then an assignment. You do not need the assignment for this: https://psalm.dev/r/f747b16b76 and if you add the assignment, the result is the same: https://psalm.dev/r/f6d3f5ba92

orklah avatar Sep 18 '21 06:09 orklah

I found these snippets:

https://psalm.dev/r/f747b16b76
<?php

function getData(int $nrOfRetries = 0): void
{
    try {
        if( $nrOfRetries < 10 ) {                
            throw new \Exception('do another iteration', E_ERROR);
        }
    } catch (\Exception $e) {
        getData($nrOfRetries + 1);
    }
}
Psalm output (using commit 37362b3):

No issues!
https://psalm.dev/r/f6d3f5ba92
<?php

function getData(int $nrOfRetries = 0): void
{
    try {
        if( $nrOfRetries < 10 ) {                
            throw new \Exception('do another iteration', E_ERROR);
        }
    } catch (\Exception $e) {
        getData($nrOfRetries = $nrOfRetries + 1);
    }
}
Psalm output (using commit 37362b3):

INFO: UnusedVariable - 10:17 - $nrOfRetries is never referenced or the value is not used

psalm-github-bot[bot] avatar Sep 18 '21 06:09 psalm-github-bot[bot]

You are right. I did not realize that (++$var) was an implicit assignment. Sorry for the comment. I fixed it with a simple addition.

thepercival avatar Sep 18 '21 07:09 thepercival

Encountered this exact case, can we expect a resolution of this at some point? Or can someone point me in the right direction so I can try to send a PR to solve this?

iwiznia avatar Sep 30 '25 18:09 iwiznia