phpstan/phpstan-webmozart-assert

Assert::allIsInstanceOf evaluates to non iterables

herndlm opened this issue · 3 comments

Having something like

final class PhpStanTest
{
    /**
     * @return stdClass[]
     */
    public function foo(bool $bar): array
    {
        $result = $bar ? [new stdClass(), new stdClass()] : false;

        Assert::allIsInstanceOf($result, stdClass::class);

        return $result;
    }
}

falsely reports

Method PhpStanTest::foo() should return array<stdClass> but returns array<int, stdClass>|false.

It cannot be false though because the all* methods are internally checking for iterables in https://github.com/webmozarts/assert/blob/master/src/Assert.php#L1947

I would love to help out here but do not know yet where to start. Feel free to point me there or to any starter resources if you like :)

What I found out so far:

  • AssertTypeSpecifyingExtension::arrayOrIterable is called where
  • TypeUtils::getArrays($currentType) returns an empty array which leads to the elseif clause where
  • (new IterableType(new MixedType(), new MixedType()))->isSuperTypeOf($currentType)->yes() is returning false (the trinary internally is set to maybe) which leads to
  • return new SpecifiedTypes([], []);

$currentType is
image

I guess it should enter the elseif where it would create an iterable type and I also guess the ConstantBooleanType should not even be there or be ignored because of all* internals or so.

To be continued hopefully..

Fixed: dcb3839

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.