psalm icon indicating copy to clipboard operation
psalm copied to clipboard

Assert reconciliation doesn't work for templates until called twice

Open SCIF opened this issue 2 years ago • 1 comments

The issue is spotted on L22. But the most interesting magic happen if assertable method called twice — reconciliation works in this case (L29)! Such behavior advises me that fix can be trivial for those familiar in internals. I could be wrong though :D

https://psalm.dev/r/d667ca7193

SCIF avatar Aug 04 '22 10:08 SCIF

I found these snippets:

https://psalm.dev/r/d667ca7193
<?php
/**
* @psalm-immutable
* @template T
*/
class A {
    /** @psalm-assert-if-true !null $this->some() */
    function assertIfTrue(): bool {
        return true;
    }

    /** @return null|T */
    function some() {
        return null;
    }
}
    
/** @var A<int> $a */

if ($a->assertIfTrue()) {
    $b = $a->some();
    /** @psalm-trace $b */;
}

/** @var A<int> $a2 */
$a2->some(); //     <-------    Miracle is happening here
if ($a2->assertIfTrue()) {
    $b = $a2->some();
    /** @psalm-trace $b */;
}
Psalm output (using commit 24f7920):

INFO: Trace - 22:27 - $b: T:A as mixed

ERROR: UnusedMethodCall - 26:6 - The call to A::some is not used

INFO: Trace - 29:27 - $b: int

INFO: UnusedVariable - 21:5 - $b is never referenced or the value is not used

INFO: UnusedVariable - 28:5 - $b is never referenced or the value is not used

psalm-github-bot[bot] avatar Aug 04 '22 10:08 psalm-github-bot[bot]