Skip to content

Commit

Permalink
Make value-of<...> lazier
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Sep 14, 2023
1 parent 0a2a6ea commit 234f77d
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 15 deletions.
16 changes: 1 addition & 15 deletions src/PhpDoc/TypeNodeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -696,22 +696,8 @@ static function (string $variance): TemplateTypeVariance {
return new ErrorType();
} elseif ($mainTypeName === 'value-of') {
if (count($genericTypes) === 1) { // value-of<ValueType>
$genericType = $genericTypes[0];
if ($genericType->isEnum()->yes()) {
$valueTypes = [];
foreach ($genericType->getEnumCases() as $enumCase) {
$valueType = $enumCase->getBackingValueType();
if ($valueType === null) {
continue;
}

$valueTypes[] = $valueType;
}

return TypeCombinator::union(...$valueTypes);
}
$type = new ValueOfType($genericTypes[0]);

$type = new ValueOfType($genericType);
return $type->isResolvable() ? $type->resolve() : $type;
}

Expand Down
14 changes: 14 additions & 0 deletions src/Type/ValueOfType.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,20 @@ public function isResolvable(): bool

protected function getResult(): Type
{
if ($this->type->isEnum()->yes()) {
$valueTypes = [];
foreach ($this->type->getEnumCases() as $enumCase) {
$valueType = $enumCase->getBackingValueType();
if ($valueType === null) {
continue;
}

$valueTypes[] = $valueType;
}

return TypeCombinator::union(...$valueTypes);
}

return $this->type->getIterableValueType();
}

Expand Down
5 changes: 5 additions & 0 deletions tests/PHPStan/Analyser/NodeScopeResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,11 @@ public function dataFileAsserts(): iterable
yield from $this->gatherAssertTypes(__DIR__ . '/data/array-sum.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/array-plus.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-4573.php');

if (PHP_VERSION_ID >= 80100) {
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-9881.php');
}

yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-4577.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-4579.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-3321.php');
Expand Down
27 changes: 27 additions & 0 deletions tests/PHPStan/Analyser/data/bug-9881.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php // lint >= 8.1

namespace Bug9881;

use BackedEnum;
use function PHPStan\Testing\assertType;

class HelloWorld
{
/**
* @template B of BackedEnum
* @param B[] $enums
* @return value-of<B>[]
*/
public static function arrayEnumToStrings(array $enums): array
{
return array_map(static fn (BackedEnum $code): string|int => $code->value, $enums);
}
}

enum Test: string {
case DA = 'da';
}

function (Test ...$da): void {
assertType('array<\'da\'>', HelloWorld::arrayEnumToStrings($da));
};

0 comments on commit 234f77d

Please sign in to comment.