vimeo / psalm

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

[4.25.0] InvalidArgument for result of a method with a static return type #8330

Closed vudaltsov closed 2 years ago

vudaltsov commented 2 years ago
<?php

declare(strict_types=1);

namespace HappyInc;

abstract class A
{
}

final class B extends A
{
    public static function create(): static
    {
        return new self();
    }
}

final class Service
{
    public function do(): void
    {
        $this->acceptA(B::create());
    }

    private function acceptA(A $_a): void
    {
    }
}

gives

ERROR: InvalidArgument - src/A.php:23:24 - Argument 1 of HappyInc\Service::acceptA expects HappyInc\A, HappyInc\Service provided (see https://psalm.dev/004)
        $this->acceptA(B::create());

in 4.25.0.

By the way, for some reason https://psalm.dev/r/6081a71dec says "No issues!".

psalm-github-bot[bot] commented 2 years ago

I found these snippets:

https://psalm.dev/r/6081a71dec ```php acceptA(B::create()); } private function acceptA(A $_a): void { } } ``` ``` Psalm output (using commit 7c4228f): No issues! ```
vudaltsov commented 2 years ago

Oh, I see, psalm.dev is at 7c4228f, not d7cd84c.

orklah commented 2 years ago

Hey @someniatko , it could be a result of https://github.com/vimeo/psalm/pull/8249. Would you mind taking a look?

VincentLanglet commented 2 years ago

I have the same issue with the following code https://psalm.dev/r/3765f8a43d

If you need a reproducer, you can try https://github.com/sonata-project/SonataAdminBundle/blob/4.x/src/FieldDescription/TypeGuesserChain.php#L57 Which has two more issue since 4.25

ERROR: MoreSpecificReturnType - src/FieldDescription/TypeGuesserChain.php:57:73 - The declared return type 'Symfony\Component\Form\Guess\TypeGuess|null' for Sonata\AdminBundle\FieldDescription\TypeGuesserChain::guess is more specific than the inferred return type 'Symfony\Component\Form\Guess\Guess&static|null' (see https://psalm.dev/070)
    public function guess(FieldDescriptionInterface $fieldDescription): ?TypeGuess

ERROR: LessSpecificReturnStatement - src/FieldDescription/TypeGuesserChain.php:69:16 - The type 'Symfony\Component\Form\Guess\Guess&static|null' is more general than the declared return type 'Symfony\Component\Form\Guess\TypeGuess|null' for Sonata\AdminBundle\FieldDescription\TypeGuesserChain::guess (see https://psalm.dev/129)
        return TypeGuess::getBestGuess($guesses);

If it require a rework of static, might be worth taking a look at https://github.com/vimeo/psalm/issues/5938 too.

psalm-github-bot[bot] commented 2 years ago

I found these snippets:

https://psalm.dev/r/3765f8a43d ```php , parent type array{TypeGuess} provided ```
someniatko commented 2 years ago

@orklah I will take a look tomorrow. My suspect is hasStaticInType() returned false for some reason, but that's really strange, there should be enough tests already written, one of which should have caught this.

AndrolGenhald commented 2 years ago

@vudaltsov does it still happen if you return new static() instead of new self()? Maybe that's the culprit?

vudaltsov commented 2 years ago

@AndrolGenhald, no, it gives the same error. Anyway, in a final class it's valid to return new self in a : static method.