psalm icon indicating copy to clipboard operation
psalm copied to clipboard

FalsePositive InvalidArgument with generics

Open VincentLanglet opened this issue 2 years ago • 2 comments

Hi @orklah,

I can't understand the error reported by https://psalm.dev/r/54c066ce8b Is it a false positive ?

VincentLanglet avatar Aug 19 '22 15:08 VincentLanglet

I found these snippets:

https://psalm.dev/r/54c066ce8b
<?php

/**
 * @phpstan-template-covariant T of object
 */
interface ProxyQueryInterface {}

/**
 * @phpstan-template T of ProxyQueryInterface
 */
interface DatagridBuilderInterface {}

/**
 * @phpstan-template T of ProxyQueryInterface
 */
interface DatagridInterface {}

/**
 * @phpstan-template T of object
 */
interface AdminInterface {}

/**
 * @phpstan-template T of object
 */
class DatagridMapper
{
    /**
     * @phpstan-param DatagridBuilderInterface<ProxyQueryInterface<T>> $datagridBuilder
     * @phpstan-param DatagridInterface<ProxyQueryInterface<T>>        $datagrid
     * @phpstan-param AdminInterface<T> $admin
     *
     * @psalm-suppress UndefinedThisPropertyAssignment
     */
    public function __construct(
        DatagridBuilderInterface $datagridBuilder,
        DatagridInterface $datagrid,
        AdminInterface $admin
    ) {
        $this->admin = $admin;
        $this->builder = $datagridBuilder;
        $this->datagrid = $datagrid;
    }
}

/**
 * @template T of object
 * @implements AdminInterface<T>
 */
abstract class Foo implements AdminInterface
{
    /** @var DatagridInterface<ProxyQueryInterface<T>> $datagrid */
    public $datagrid;
    
    public function test(): DatagridMapper
    {   
        return new DatagridMapper($this->getDatagridBuilder(), $this->datagrid, $this);
    }
    
    /** @return DatagridBuilderInterface<ProxyQueryInterface<T>> */
    abstract public function getDatagridBuilder(): DatagridBuilderInterface;
}
Psalm output (using commit afe85fa):

ERROR: InvalidArgument - 57:35 - Argument 1 of DatagridMapper::__construct expects DatagridBuilderInterface<ProxyQueryInterface<object>>, DatagridBuilderInterface<ProxyQueryInterface<T:Foo as object>> provided

ERROR: InvalidArgument - 57:64 - Argument 2 of DatagridMapper::__construct expects DatagridInterface<ProxyQueryInterface<object>>, DatagridInterface<ProxyQueryInterface<T:Foo as object>> provided

psalm-github-bot[bot] avatar Aug 19 '22 15:08 psalm-github-bot[bot]

Pretty sure that's a false positive. Looks like it's fine if you don't use a constraint, but I'm pretty sure we've also got a bunch of false negatives for templates without constraints, which might be why this happens to work.

AndrolGenhald avatar Aug 19 '22 18:08 AndrolGenhald