Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

False-positive RedundantCondition #7776

Closed
gharlan opened this issue Mar 12, 2022 · 11 comments
Closed

False-positive RedundantCondition #7776

gharlan opened this issue Mar 12, 2022 · 11 comments
Labels

Comments

@gharlan
Copy link
Contributor

gharlan commented Mar 12, 2022

https://psalm.dev/r/1b1ca51578

<?php

/**
 * @param DateTime[] $bar
 */
function foo(?DateTime $foo, array $bar): void {
    if (
        $foo && !in_array($foo, $bar, true)
        || !$foo && $bar
    ) {
        return;
    }
    
    if ($foo) {
    }
}
@psalm-github-bot
Copy link

I found these snippets:

https://psalm.dev/r/1b1ca51578
<?php

/**
 * @param DateTime[] $bar
 */
function foo(?DateTime $foo, array $bar): void {
    if (
        $foo && !in_array($foo, $bar, true)
        || !$foo && $bar
    ) {
        return;
    }
    
    if ($foo) {
    }
}
Psalm output (using commit f0b2142):

ERROR: RedundantCondition - 14:9 - Operand of type DateTime is always truthy

@orklah orklah added the bug label Mar 12, 2022
@AndrolGenhald
Copy link
Collaborator

AndrolGenhald commented Mar 12, 2022

It looks like the issue is with the negation of strict in_array, this and this should be identical, but Psalm seems to think that if $int is not in $ints then it must not be an int, which is incorrect. It's probably just comparing the types somewhere without accounting for the fact that they can have the same type but still be different.

Scratch that, not sure what I was thinking there. Here's something that's actually useful though, doing a strict comparison against null fixes it.

@psalm-github-bot
Copy link

I found these snippets:

https://psalm.dev/r/39b01f458c
<?php

/** @param list<int> $ints */
function foobar(?int $int, array $ints): bool
{
    if ($int === null) {
        return true;
    }

    return in_array($int, $ints, true);
}
Psalm output (using commit f0b2142):

No issues!
https://psalm.dev/r/37e040f7fe
<?php

/** @param list<int> $ints */
function foobar(?int $int, array $ints): bool
{
    if (!in_array($int, $ints, true)) {
        return false;
    }

    return $int === null;
}
Psalm output (using commit f0b2142):

ERROR: TypeDoesNotContainNull - 10:12 - int does not contain null

@AndrolGenhald
Copy link
Collaborator

Well I git bisected it to #6233, but I'm not actually sure that's at fault, it seems more like a boolean algebra problem. I think this is the same problem without in_array (proof it's wrong since I keep messing it up). git bisecting that points to a832d77, which seems more relevant. Maybe @muglug can help with this?

@psalm-github-bot
Copy link

I found these snippets:

https://psalm.dev/r/3395485445
<?php

function foo(?int $foo, int $bar): void {
    if (
        $foo && $foo !== 1
        || !$foo && $bar
    ) {
        return;
    }
    
    if ($foo === null) {
    }
}
Psalm output (using commit f0b2142):

ERROR: TypeDoesNotContainNull - 11:9 - int does not contain null

@muglug
Copy link
Collaborator

muglug commented Mar 13, 2022

The conjunctive normal form version (which Psalm uses internally) also shows the bug: https://psalm.dev/r/edc2283627

@psalm-github-bot
Copy link

I found these snippets:

https://psalm.dev/r/edc2283627
<?php

function baz(?int $foo): void {
    if (
        (!$foo || $foo !== 5) && ($foo || rand(0,1)) && ($foo !== 5 || rand(0, 1))
    ) {
        return;
    }
    
    if ($foo === null) {}
}
Psalm output (using commit f0b2142):

ERROR: TypeDoesNotContainNull - 10:9 - int does not contain null

muglug added a commit that referenced this issue Mar 13, 2022
When a new clause contains tautology it can be disregarded entirely
@muglug
Copy link
Collaborator

muglug commented Mar 13, 2022

Fixed in the master branch

@muglug muglug closed this as completed Mar 13, 2022
@muglug
Copy link
Collaborator

muglug commented Mar 13, 2022

The culrpit was bad logic here.

It was simplifying (A || B || !B) to (A), whereas it should have simplified it to true

@gharlan
Copy link
Contributor Author

gharlan commented Mar 13, 2022

@muglug Thanks for the quick fix. But shouldn't the fix target the 4.x branch?

@orklah
Copy link
Collaborator

orklah commented Mar 13, 2022

We're starting to have big differences between 4.x and master.

Fixing this in 4.x means basically fixing an old version then rebasing that on master and getting conflicts, so basically fixing it twice.

Recent events kinda disrupted availability and motivation of the team, I was hoping Psalm 5 would be available by now. In the meantime, it means some bugs are getting fixed on master unfortunately.

However, feel free to switch to our master branch and report us any bug that could appear!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants