vimeo / psalm

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

Template constraint issues with literals #8247

Open AndrolGenhald opened 2 years ago

AndrolGenhald commented 2 years ago

When a class has a template constraint, using a templated type as a parameter for a function that doesn't specify the template incorrectly changes the variable to have the constraint type instead of the templated type: https://psalm.dev/r/6b46d38af2

When there is no template constraint this doesn't happen: https://psalm.dev/r/cd80832550

In fact, both of these are incorrect because the template isn't covariant. You can see here that when non-literals are involved the actual issue is shown.

I believe this special handling of literals was adding so that there wouldn't be a bunch of "false positives" for stuff like this, but I think this special handling should be removed once #8066 is fixed.

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

I found these snippets:

https://psalm.dev/r/6b46d38af2 ```php $foobar * @return Foobar */ function foo(Foobar $foobar): Foobar { /** @psalm-trace $foobar */; bar($foobar); /** @psalm-trace $foobar */; return $foobar; } function bar(Foobar $foobar): void {} ``` ``` Psalm output (using commit 6d45003): INFO: Trace - 12:32 - $foobar: Foobar INFO: Trace - 14:32 - $foobar: Foobar ERROR: InvalidReturnStatement - 15:12 - The inferred type 'Foobar' does not match the declared return type 'Foobar' for foo ERROR: InvalidReturnType - 8:12 - The declared return type 'Foobar' for foo is incorrect, got 'Foobar' INFO: UnusedParam - 18:21 - Param $foobar is never referenced in this method ```
https://psalm.dev/r/cd80832550 ```php $foobar * @return Foobar */ function foo(Foobar $foobar): Foobar { /** @psalm-trace $foobar */; bar($foobar); /** @psalm-trace $foobar */; return $foobar; } function bar(Foobar $foobar): void {} ``` ``` Psalm output (using commit 6d45003): INFO: Trace - 12:32 - $foobar: Foobar INFO: Trace - 14:32 - $foobar: Foobar INFO: UnusedParam - 18:21 - Param $foobar is never referenced in this method ```
https://psalm.dev/r/59f7c5b08f ```php $foobar * @return Foobar */ function foo(Foobar $foobar): Foobar { /** @psalm-trace $foobar */; bar($foobar); /** @psalm-trace $foobar */; return $foobar; } function bar(Foobar $foobar): void {} ``` ``` Psalm output (using commit 6d45003): INFO: Trace - 12:32 - $foobar: Foobar ERROR: InvalidArgument - 13:9 - Argument 1 of bar expects Foobar, Foobar provided INFO: Trace - 14:32 - $foobar: Foobar INFO: UnusedParam - 18:21 - Param $foobar is never referenced in this method ```
https://psalm.dev/r/c8596330d4 ```php $items */ public function __construct(array $items) {} } /** @param InvariantCollection $_ints */ function foobar($_ints): void {} foobar(new InvariantCollection([1, 2, 3])); // Technically illegal since this is an InvariantCollection<1|2|3> ``` ``` Psalm output (using commit 6d45003): No issues! ```