vimeo / psalm

A static analysis tool for finding errors in PHP applications
https://psalm.dev
MIT License
5.55k stars 659 forks source link

Psalm complaining about mixed template types, even if the template type is resolved correctly #5060

Open danog opened 3 years ago

danog commented 3 years ago

https://psalm.dev/r/5df148c0b9

As you can see, psalm is complaining about a mixed|uninferrable return type un Unboxer::unbox, even if the return type is correctly inferred afterwards, once the template type Unboxer::T and the inferred template type Unboxer::TFinal are both populated. The same "T as mixed" template type is returned in Box::unbox, and no issue is present there.

Actually, hovering over the left and right ternary branches in Unboxer::unbox, I see that psalm resolves a "mixed" (not "TFinal as mixed") type on "$this->boxOrVal->unbox()", and an "empty-mixed" type on the right branch, instead of "TFinal as mixed".

psalm-github-bot[bot] commented 3 years ago

I found these snippets:

https://psalm.dev/r/5df148c0b9 ```php val = $val; } /** * @return T */ public function unbox() { return $this->val; } } /** * @template TFinal * @template T as Box|TFinal */ class Unboxer { /** * @var T */ public $boxOrVal; /** * @param T $boxOrVal */ public function __construct($boxOrVal) { $this->boxOrVal = $boxOrVal; } /** * @psalm-return TFinal */ public function unbox() { return $this->boxOrVal instanceof Box ? $this->boxOrVal->unbox() : $this->boxOrVal; } } $a = new Unboxer(new Box(0)); /** @psalm-trace $res */ $res = $a->unbox(); $a = new Unboxer(0); /** @psalm-trace $res */ $res = $a->unbox(); ``` ``` Psalm output (using commit 9e05254): INFO: Trace - 50:1 - $res: int(0) INFO: Trace - 54:1 - $res: int(0) INFO: UnusedVariable - 50:1 - $res is never referenced or the value is not used INFO: UnusedVariable - 54:1 - $res is never referenced or the value is not used ERROR: DocblockTypeContradiction - 44:76 - Docblock-defined type T:Unboxer as (Box)|(TFinal:Unboxer as mixed) for $this->boxOrVal is always Box INFO: MixedReturnStatement - 44:16 - Could not infer a return type INFO: MixedInferredReturnType - 41:22 - Could not verify return type 'TFinal' for Unboxer::unbox ```