vimeo / psalm

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

Add checks similar to TypeDoesNotContainType for loose equality (==, !=) conditions? #1712

Open TysonAndre opened 5 years ago

TysonAndre commented 5 years ago

Some examples of code it might be useful for psalm to warn about are below. Currently, psalm does not warn, because the code uses == instead of ===.

E.g. could add a QuestionableLooseEqualityCheck comparing int to string(false)' issue type for the checks involving strings/numbers/null on either side

<?php

function test_strpos(string $str) : bool {
    // This is questionable code using `==`.
    // The 2 below conditions can be true ("0 == 'nonnumericstring'" in current releases of php),
    //   but for the wrong reasons.
    var_export($str == null);
    var_export(strpos($str, 'target') == 'false');

    $a = true;
    $b = false;
    if ($a == $b) {
        // This does not emit TypeDoesNotContainType, but could
        echo "unreachable\n";
    }
    if ($a === $b) {
        // This does emit TypeDoesNotContainType
        echo "unreachable\n";
    }

    // Or impossible conditions.
    return strpos($str, 'target') == ['questionable'];
}
muglug commented 5 years ago

basically it's useful when comparing two unions A and B that don't both have the same scalar type, where A and/or B has an always truthy or always falsy value

e.g.

string compared to null, string|false compared to non-empty-array, int|false compared to array<empty, empty>

Marking as a bug because Psalm really should have caught the first line as it did the next: https://psalm.dev/r/e7ff542f98 (also maybe related to #1684)