psalm
psalm copied to clipboard
Allow for validation guards without complaining
While psalm is absolutely correct in deducing that with the annotated type the condition cannot ever be true, it's annoying for library authors to suppress the psalm errors, as the goal is to provide some runtime safety for users who might not use psalm. Or even just catch cases where the psalm static analysis failed (or was erroneously suppressed).
I found it an especially common pattern with ranges like positive-int.
https://psalm.dev/r/ad2a2cb6dd
I would propose that any branches which unconditionally throw (i.e. cause a never
return type for the branch) - if the function as a whole doesn't unconditionally throw, the guards are accepted as valid by psalm.
I could also imagine this feature request being implemented as a psalm.xml option rather than just ignoring it by default.
I found these snippets:
https://psalm.dev/r/ad2a2cb6dd
<?php
/**
* @param positive-int $i
* @return negative-int
*/
function returnsNegativeInt(int $i): int {
if ($i <= 0) {
throw new \Error("Invalid argument $i");
}
return -$i;
}
Psalm output (using commit 4b2c698):
ERROR: DocblockTypeContradiction - 8:9 - Docblock-defined type int<1, max> for $i is always >= 0
ERROR: InvalidCast - 9:44 - never cannot be cast to string
(Nitpick: Docblock-defined type int<1, max> for $i is always >= 0
also should read is always > 0
or >= 1
)
Yeah that's quite on common on codebases of libraries, usable by users without a static analyzer to catch misuses of APIs.
A good idea would be to enable the behavior only on checks made on parameters of functions/methods that are public API, only for docblock-originated types, not types enforced by runtime typehints.