Skip to content

Commit

Permalink
Fix infinite recursion for template intersection type accepts()
Browse files Browse the repository at this point in the history
  • Loading branch information
rvanvelzen authored and ondrejmirtes committed Jun 21, 2022
1 parent 29ca9b2 commit e4a1b67
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 5 deletions.
5 changes: 0 additions & 5 deletions src/Type/IntersectionType.php
Expand Up @@ -22,7 +22,6 @@
use PHPStan\Type\Generic\TemplateType;
use PHPStan\Type\Generic\TemplateTypeMap;
use PHPStan\Type\Generic\TemplateTypeVariance;
use PHPStan\Type\Generic\TemplateUnionType;
use PHPStan\Type\Traits\NonGeneralizableTypeTrait;
use PHPStan\Type\Traits\NonRemoveableTypeTrait;
use function array_map;
Expand Down Expand Up @@ -144,10 +143,6 @@ public function isSubTypeOf(Type $otherType): TrinaryLogic

public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLogic
{
if ($acceptingType instanceof self || ($acceptingType instanceof UnionType && !$acceptingType instanceof TemplateUnionType)) {
return $acceptingType->accepts($this, $strictTypes);
}

$results = [];
foreach ($this->getTypes() as $innerType) {
$results[] = $acceptingType->accepts($innerType, $strictTypes);
Expand Down
8 changes: 8 additions & 0 deletions tests/PHPStan/Analyser/AnalyserIntegrationTest.php
Expand Up @@ -859,6 +859,14 @@ public function testBug7275(): void
$this->assertNoErrors($errors);
}

public function testBug7500(): void
{
$errors = $this->runAnalyse(__DIR__ . '/data/bug-7500.php');
$this->assertCount(1, $errors);
$this->assertSame('Method Bug7500\HelloWorld::computeForFrontByPosition() should return array<T of Bug7500\PositionEntityInterface&Bug7500\TgEntityInterface> but returns array<Bug7500\PositionEntityInterface&Bug7500\TgEntityInterface>.', $errors[0]->getMessage());
$this->assertSame(38, $errors[0]->getLine());
}

/**
* @param string[]|null $allAnalysedFiles
* @return Error[]
Expand Down
48 changes: 48 additions & 0 deletions tests/PHPStan/Analyser/data/bug-7500.php
@@ -0,0 +1,48 @@
<?php declare(strict_types = 1);

namespace Bug7500;

interface PositionEntityInterface {
public function getPosition(): int;
}
interface TgEntityInterface {}

abstract class HelloWorld
{
/**
* @phpstan-template T of PositionEntityInterface&TgEntityInterface
*
* @param iterable<T> $tgs
*
* @return array<T>
*
* @throws \Exception
*/
public function computeForFrontByPosition($tgs)
{
/** @phpstan-var array<T> $res */
$res = [];

foreach ($tgs as $tgItem) {
$position = $tgItem->getPosition();

if (!isset($res[$position])) {
$res[$position] = $tgItem;
} else {
$tgItemToKeep = $this->compare($tgItem, $res[$position]);
$res[$position] = $tgItemToKeep;
}
}
ksort($res);

return $res;
}

/**
* @phpstan-template T of TgEntityInterface
* @phpstan-param T $nextTg
* @phpstan-param T $currentTg
* @phpstan-return T
*/
abstract protected function compare(TgEntityInterface $nextTg, TgEntityInterface $currentTg): TgEntityInterface;
}

0 comments on commit e4a1b67

Please sign in to comment.