phpstan-phpunit icon indicating copy to clipboard operation
phpstan-phpunit copied to clipboard

assertNotFalse() doesn't remove FALSE from the union type

Open morozov opened this issue 4 years ago • 4 comments

$ composer show | grep phpstan
phpstan/phpdoc-parser                          0.4.4   PHPDoc parser with support for nul...
phpstan/phpstan                                0.12.50 PHPStan - PHP Static Analysis Tool
phpstan/phpstan-strict-rules

Consider the following test:

<?php

declare(strict_types=1);

namespace SomeNamespace;

use PHPUnit\Framework\TestCase;

use function rand;

class PHPStanTest extends TestCase
{
    public function testCurrentDate(): void
    {
        $data = $this->f2();
        self::assertNotFalse($data);

        $this->f1(...$data);
    }

    private function f1(int $a, int $b): void
    {
    }

    /** @return array<int,int>|false */
    private function f2()
    {
        return rand(-1, 1) > 0 ? [1, 2] : false;
    }
}

PHPStan flags it as:

$ phpstan a PHPStanTest.php
Note: Using configuration file phpstan.neon.dist.
 1/1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%

 ------ -----------------------------------------------------------------------------
  Line   PHPStanTest.php
 ------ -----------------------------------------------------------------------------
  18     Only iterables can be unpacked, array<int, int>|false given in argument #1.
 ------ -----------------------------------------------------------------------------

 [ERROR] Found 1 error

Replacing self::assertNotFalse($data) with assert($data !== false) works around the problem.

morozov avatar Oct 17 '20 20:10 morozov

Weird. This is the equivalent of what the extension does, and it works... https://phpstan.org/r/267b2ee0-58b9-4748-9360-3da17b5a4196

ondrejmirtes avatar Oct 18 '20 09:10 ondrejmirtes

I have a similar problem with self::assertNotNull. Plain assert($var !== null) has the desired effect. Shall I open a new issue or is it the same thing underneath?

 public function testFoo(): void {
        $items = [null, new \DateTimeImmutable()];
        $var = $items[rand(0, 1)];
        self::assertNotNull($var);
        echo $var->format('Ymd'); // PHPStan error reported here
        assert($var !== null);
        echo $var->format('Ymd'); // ... but not here
    }

InvisibleSmiley avatar Oct 21 '21 08:10 InvisibleSmiley

@InvisibleSmiley Are you sure you have the phpstan-phpunit extension installed and enabled? This should work without a problem.

ondrejmirtes avatar Oct 21 '21 08:10 ondrejmirtes

I'm very sorry, I forgot to require phpstan/extension-installer in the affected project. In light of that, please disregard my previous comment.

InvisibleSmiley avatar Oct 22 '21 12:10 InvisibleSmiley