vimeo / psalm

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

Psalm does not properly infer type with instanceof static #4900

Open BenMorel opened 3 years ago

BenMorel commented 3 years ago

Consider the following code:

class WKTReader
{
    public function read(string $wkt): Geometry {}
}

abstract class Geometry
{
    /**
     * @return static
     */
    public static function fromText(string $wkt) : Geometry
    {
        $wktReader = new WKTReader();
        $geometry = $wktReader->read($wkt);

        if (! $geometry instanceof static) {
            throw new Exception();
        }

        return $geometry;
    }
}

Psalm complains with:

INFO: LessSpecificReturnStatement - 26:16 - The type 'Geometry' is more general than the declared return type 'Geometry&static' for Geometry::fromText

INFO: MoreSpecificReturnType - 15:16 - The declared return type 'Geometry&static' for Geometry::fromText is more specific than the inferred return type 'Geometry'

Even though the return type is, indeed, Geometry&static.

https://psalm.dev/r/5ba2afa441

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

I found these snippets:

https://psalm.dev/r/5ba2afa441 ```php read($wkt); if (! $geometry instanceof static) { throw new Exception(); } return $geometry; } } class Point extends Geometry { } Point::fromText('POINT (0 0)'); ``` ``` Psalm output (using commit 3b6550f): INFO: LessSpecificReturnStatement - 26:16 - The type 'Geometry' is more general than the declared return type 'Geometry&static' for Geometry::fromText INFO: MoreSpecificReturnType - 15:16 - The declared return type 'Geometry&static' for Geometry::fromText is more specific than the inferred return type 'Geometry' ```
orklah commented 3 years ago

Seems to be an issue with the negation of Geometry&static because this works: https://psalm.dev/r/9cb24166c0. I couldn't pinpoint where this is computed

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

I found these snippets:

https://psalm.dev/r/9cb24166c0 ```php read($wkt); if ($geometry instanceof static) { return $geometry; } else{ throw new Exception(); } } } class Point extends Geometry { } Point::fromText('POINT (0 0)'); ``` ``` Psalm output (using commit 3b6550f): No issues! ```