1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-22 05:41:20 +01:00
This commit is contained in:
Matt Brown 2022-04-27 01:47:02 -04:00
parent 2ef993928c
commit d064d9fc6c
2 changed files with 97 additions and 11 deletions

View File

@ -1085,18 +1085,30 @@ class CallAnalyzer
} else {
foreach ($lower_bounds as $lower_bound) {
if ($lower_bound->equality_bound_classlike === null) {
if (!in_array($lower_bound->type->getId(), $equality_types, true)) {
IssueBuffer::maybeAdd(
new InvalidArgument(
'Incompatible types found for ' . $template_name . ' (' .
$lower_bound->type->getId() . ' is not in ' .
implode(', ', $equality_types) . ')',
$code_location,
$function_id
),
$statements_analyzer->getSuppressedIssues()
);
foreach ($bounds_with_equality as $bound_with_equality) {
if (UnionTypeComparator::isContainedBy(
$statements_analyzer->getCodebase(),
$lower_bound->type,
$bound_with_equality->type
) && UnionTypeComparator::isContainedBy(
$statements_analyzer->getCodebase(),
$bound_with_equality->type,
$lower_bound->type
)) {
continue 2;
}
}
IssueBuffer::maybeAdd(
new InvalidArgument(
'Incompatible types found for ' . $template_name . ' (' .
$lower_bound->type->getId() . ' is not in ' .
implode(', ', $equality_types) . ')',
$code_location,
$function_id
),
$statements_analyzer->getSuppressedIssues()
);
}
}
}

View File

@ -3690,6 +3690,80 @@ class ClassTemplateTest extends TestCase
final class Two {}
final class Three {}',
],
'issue7825' => [
'code' => '<?php
interface Stub {}
interface ProxyQueryInterface {}
class MockObject {}
/** @phpstan-template T of ProxyQueryInterface */
interface PagerInterface {}
/** @phpstan-template T of ProxyQueryInterface */
class Datagrid
{
/** @var T */
private $query;
/** @var PagerInterface<T> */
private $pager;
/**
* @phpstan-param T $query
* @phpstan-param PagerInterface<T> $pager
*/
public function __construct(
ProxyQueryInterface $query,
PagerInterface $pager
) {
$this->pager = $pager;
$this->query = $query;
}
}
interface FormBuilderInterface {}
/** @template T of FieldDescriptionInterface */
class FieldDescriptionCollection {}
interface FieldDescriptionInterface {}
abstract class Test
{
/** @var Datagrid<ProxyQueryInterface&Stub> */
private Datagrid $datagrid;
/** @var PagerInterface<ProxyQueryInterface&Stub>&MockObject */
private $pager;
/** @var ProxyQueryInterface&Stub */
private $query;
/** @var FieldDescriptionCollection<FieldDescriptionInterface> */
private FieldDescriptionCollection $columns;
private FormBuilderInterface $formBuilder;
/**
* @psalm-template RealInstanceType of object
* @psalm-param class-string<RealInstanceType> $originalClassName
* @psalm-return MockObject&RealInstanceType
*/
abstract protected function createMock(string $originalClassName): MockObject;
/**
* @psalm-template RealInstanceType of object
* @psalm-param class-string<RealInstanceType> $originalClassName
* @psalm-return Stub&RealInstanceType
*/
abstract protected function createStub(string $originalClassName): Stub;
protected function setUp(): void
{
$this->query = $this->createStub(ProxyQueryInterface::class);
$this->columns = new FieldDescriptionCollection();
/** @var PagerInterface<ProxyQueryInterface&Stub>&MockObject $pager */
$pager = $this->createMock(PagerInterface::class);
$this->pager = $pager;
$this->datagrid = new Datagrid($this->query, $pager);
}
}',
],
];
}