psalm
psalm copied to clipboard
FalsePositive InvalidArgument with generics
Hi @orklah,
I can't understand the error reported by https://psalm.dev/r/54c066ce8b Is it a false positive ?
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
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.