psalm icon indicating copy to clipboard operation
psalm copied to clipboard

conditional return incorrectly handles non-empty-mixed with false

Open kkmuffme opened this issue 2 years ago • 2 comments

https://psalm.dev/r/6dd93dfbcb

$result should be int only, since non-empty-mixed never contains false

kkmuffme avatar Sep 25 '22 15:09 kkmuffme

I found these snippets:

https://psalm.dev/r/6dd93dfbcb
<?php

/** @var mixed $foo */

if ( !empty( $foo ) ) {
    /** @psalm-trace $foo */;
    
    $result = bar( $foo );
    /** @psalm-trace $result */;
}

/**
 * @param mixed $arg
 * @return ($arg is false ? string|false : int)
 */
function bar( $arg ) {}
Psalm output (using commit 028ac7f):

INFO: Trace - 6:29 - $foo: non-empty-mixed

INFO: Trace - 9:32 - $result: false|int|string

ERROR: InvalidReturnType - 14:12 - No return statements were found for method bar but return type 'false|int|string' was expected

psalm-github-bot[bot] avatar Sep 25 '22 15:09 psalm-github-bot[bot]

Not sure this can be fixed easily.

If I remember correctly, conditional returns works as follow:

  • if the param is mixed, we take the union of the first and second operand
  • if the param is contained by the checked type, we take the first operand
  • otherwise we take the second operand

So, non-empty-mixed is considered mixed. I think this checks takes precedence over checking the second item from the list above.

orklah avatar Sep 25 '22 18:09 orklah