Skip to content

Commit

Permalink
Array shape with optional keys might be a list
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Jul 19, 2023
1 parent b71aa34 commit 97f0039
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 3 deletions.
6 changes: 5 additions & 1 deletion src/Type/Constant/ConstantArrayTypeBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,11 @@ public function setOffsetValueType(?Type $offsetType, Type $valueType, bool $opt
$min = min($this->nextAutoIndexes);
$max = max($this->nextAutoIndexes);
if ($offsetType->getValue() > $min) {
$this->isList = TrinaryLogic::createNo();
if ($offsetType->getValue() <= $max) {
$this->isList = $this->isList->and(TrinaryLogic::createMaybe());
} else {
$this->isList = TrinaryLogic::createNo();
}
}
if ($offsetType->getValue() >= $max) {
/** @var int|float $newAutoIndex */
Expand Down
1 change: 1 addition & 0 deletions tests/PHPStan/Analyser/NodeScopeResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ public function dataFileAsserts(): iterable
yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Comparison/data/bug-2550.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-2899.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/preg_split.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/array-shape-list-optional.php');

if (PHP_VERSION_ID < 80000) {
yield from $this->gatherAssertTypes(__DIR__ . '/data/bcmath-dynamic-return-php7.php');
Expand Down
26 changes: 26 additions & 0 deletions tests/PHPStan/Analyser/data/array-shape-list-optional.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace ArrayShapeListOptional;

use function PHPStan\Testing\assertType;

class Foo
{

/**
* @param list{0: string, 1: int, 2?: string, 3?: string} $valid1
* @param list{0: string, 1: int, 2?: string, 4?: string} $invalid1
* @param list{0: string, 1: int, 2?: string, foo?: string} $invalid2
*/
public function doFoo(
$valid1,
$invalid1,
$invalid2
): void
{
assertType('array{0: string, 1: int, 2?: string, 3?: string}&list', $valid1);
assertType('*NEVER*', $invalid1);
assertType('*NEVER*', $invalid2);
}

}
4 changes: 2 additions & 2 deletions tests/PHPStan/Rules/Methods/ReturnTypeRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -924,12 +924,12 @@ public function testLists(): void
[
"Method ReturnList\Foo::getList1() should return list<string> but returns array{0?: 'foo', 1?: 'bar'}.",
10,
"array{0?: 'foo', 1?: 'bar'} is not a list.",
"array{0?: 'foo', 1?: 'bar'} might not be a list.",
],
[
"Method ReturnList\Foo::getList2() should return list<string> but returns array{0?: 'foo', 1?: 'bar'}.",
19,
"array{0?: 'foo', 1?: 'bar'} is not a list.",
"array{0?: 'foo', 1?: 'bar'} might not be a list.",
],
]);
}
Expand Down

0 comments on commit 97f0039

Please sign in to comment.