psalm icon indicating copy to clipboard operation
psalm copied to clipboard

Type error only occurring locally when analysing entire codebase

Open ciaranmcnulty opened this issue 3 years ago • 3 comments

We have this method in cucumber/common: https://github.com/cucumber/common/blob/9945048fe4668dce3b3118670488b4c2ca79a884/gherkin/php/src/AstNode.php#L58

Builds in CI using the cucumber/cucumber-build container are passing: https://app.circleci.com/pipelines/github/cucumber/common/12814/workflows/6e3f569e-8a0c-4492-904e-de6284d25109/jobs/488558

When I run psalm just on that file (psalm --no-cache src/AstNode.php, there are no errors. Nor do I get an error when trying to reproduce on psalm.dev

However when running psalm on the whole codebase, we get this error:

ERROR: InvalidReturnType - src/AstNode.php:56:22 - The declared return type '(S:fn-cucumber\gherkin\astnode::getsingle as object)|null' for Cucumber\Gherkin\AstNode::getSingle is incorrect, got '(S:fn-cucumber\gherkin\astnode::getsingle as object)|(TGeneratedFromParam2:fn-cucumber\gherkin\astnode::getsingle as null|object)' (see https://psalm.dev/011)
     * @psalm-return ($defaultValue is null ? S|null : S )

This seems to be triggered by $defaultValue being optional - trace shows it as TGeneratedFromParam2:fn-cucumber\gherkin\astnode::getsingle as null|object but if I take the = null away it correctly is typed as S:fn-cucumber\gherkin\astnode::getsingle as object which fixes the return type issue.

I have tried:

  • --clear-cache
  • bisecting across cucumber versions. Very old checkouts show this error too
  • trying different psalm versions. I've reproduced with 4.29.0, 4.28.0 and back to 4.26.0

It's very mysterious that the CI build in the same container doesn't show this error, nor the single-file analysis

ciaranmcnulty avatar Oct 12 '22 10:10 ciaranmcnulty

Couldn't reproduce either on psalm.dev: https://psalm.dev/r/8402a9a656

Could you maybe try to analyze with Psalm 5?

orklah avatar Oct 12 '22 17:10 orklah

I found these snippets:

https://psalm.dev/r/8402a9a656
<?php

class A{
	/**
     * @template S of object
     *
     * @param class-string<S> $expectedType
     * @param S|null $defaultValue
     *
     * @psalm-return ($defaultValue is null ? S|null : S )
     */
    function getSingle(string $expectedType, ?object $defaultValue = null): mixed
    {
        $items = $this->getItems($expectedType);

        return $items[0] ?? $defaultValue;
    }

	/**
     * @template T of object
     *
     * @param class-string<T> $expectedType
     *
     * @psalm-return list<T>
     */
    function getItems(string $expectedType): array
    {
        return [];
    }
}
Psalm output (using commit eb6a347):

No issues!

psalm-github-bot[bot] avatar Oct 12 '22 17:10 psalm-github-bot[bot]

For reference, this is solved when using Psalm 6.13.1

stof avatar Nov 04 '25 14:11 stof