psalm: False positive: mixed is a reserved word
Reproducer: https://github.com/derrabus/psalm-mixed-reproducer
When installing Symfony Cache 6 in a project, I get a strange error:
ERROR: ReservedWord - src/MyClass.php:12:19 - mixed is a reserved word (see https://psalm.dev/095)
if (1 === $cache->getItem(__FUNCTION__)->get()) {
As you can see, the highlighted code does not contain the mixed
keyword at all.
If I downgrade Symfony cache to 5.4, the error is gone.
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 19 (5 by maintainers)
Commits related to this issue
- Workaround null & mixed being ReservedWords Symfony 6 added return types to most of it's signatures. This is reported as ReservedWords by Psalm. See https://github.com/vimeo/psalm/issues/7026 and h... — committed to fbourigault/Propel2 by fbourigault 2 years ago
- Workaround null & mixed being ReservedWords Symfony 6 added return types to most of it's signatures. This is reported as ReservedWords by Psalm. See https://github.com/vimeo/psalm/issues/7026 and h... — committed to fbourigault/Propel2 by fbourigault 2 years ago
- Add configuration value `auto_php_version` We now support the new configuration option `auto_php_version` (default: true) to automatically pass currenct PHP runtime version to psalm via parameter `--... — committed to phpcq/plugin-psalm by discordier 2 years ago
This could have helped understand the issue, but not fixing it. For now, the only fix I see is either ignoring the error in the config as done by Doctrine, or analysing the project based on the current PHP version (with which the deps are compatible).
if you cannot parse the dependencies based on their own min PHP version, this looks like the best behavior, as it will produce a working analysis. We should still find a way for this warning to be opted-out IMO, so that projects running multiple CI jobs on different PHP versions can disable this warning (as they are doing that check in the other CI job)
Please note that the feature that takes the min php version from composer.json was just designed for ease of use, especially for users that are beginners in using Psalm and don’t have yet all the configs in mind.
It is just a default php version that makes sense for a lot of users to analyse with.
Now the case for libraries is different. In a majority of cases, the library have to support more than one version of PHP and may want to be forward compatible.
If that’s the case, there is more than keywords that can change in dependencies. Old versions of dependencies may have a completely different API, or simply a different param type or return type.
It feels weird to focus on the fact that mixed is not really a reserved keyword and not consider at all that, if the dependencies were really installed in PHP 7.3, the param that’s mixed in PHP 8.1 could have been a string at that time.
tl;dr: If you run Psalm in version 7.3 against PHP 8.1 dependencies, Psalm may miss a lot of issues. I think a sane way to approach this would be to run composer with --prefer-lowest and analyse with 7.3, then run normally and analyse with 8.1.
I suppose you would get that error if class existed, and wasn’t named ‘mixed’. Psalm just thinks it found a more serious issue that makes reporting other potential issues in that expression superfluous.
Reporting UndefinedClass here would be technically correct, but I guess it was judged that errors like ‘UndefinedClass: class void does not exist’ were too confusing (similar to https://3v4l.org/qktSv#v7.0.33), and it was better to flag potential keywords with a separate issue type (this also allows you to selectively suppress it).
Right, but then again, Psalm is supposed to check my code for errors and not the dependencies’. Also, it is odd that this is the only error reported: Symfony 6 uses quite some more PHP 8 language features, why is Psalm complaining about the mixed type only?
If you want a more real-life example, we’ve found this in the CI of https://github.com/doctrine/dbal. Here, the codebase has to remain compatible with PHP 7.3, but allows dependencies that operate on a higher language level.
But this is not what I want. If my codebase would really use the mixed keyword, I certainly want to know. Should I run Psalm twice with different sets of dependencies or what would your recommondation be in that regard?
Even if I was just using the tool wrong, I still believe that the output should be different: