Skip to content

Commit

Permalink
Fix int-range return type for range()
Browse files Browse the repository at this point in the history
  • Loading branch information
dantleech committed Jan 6, 2024
1 parent 72509ed commit 9d3eba2
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/Type/Php/RangeFunctionReturnTypeExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
$isStepInteger = $stepType->isInteger()->yes();

if ($isInteger && $isStepInteger) {
if ($argType instanceof IntegerRangeType) {
return AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), $argType));
}
return AccessoryArrayListType::intersectWith(new ArrayType(new IntegerType(), new IntegerType()));
}

Expand Down
6 changes: 6 additions & 0 deletions tests/PHPStan/Analyser/AnalyserIntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1193,6 +1193,12 @@ public function testBug9459(): void
$this->assertSame(10, $errors[0]->getLine());
}

public function testBug9573(): void
{
$errors = $this->runAnalyse(__DIR__ . '/data/bug-9573.php');
$this->assertNoErrors($errors);
}

public function testBug9039(): void
{
$errors = $this->runAnalyse(__DIR__ . '/data/bug-9039.php');
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 @@ -609,6 +609,7 @@ public function dataFileAsserts(): iterable
yield from $this->gatherAssertTypes(__DIR__ . '/data/array-unshift.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/array_map_multiple.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/range-numeric-string.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/range-int-range.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/missing-closure-native-return-typehint.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-4741.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/more-type-strings.php');
Expand Down
17 changes: 17 additions & 0 deletions tests/PHPStan/Analyser/data/bug-9573.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php declare(strict_types = 1);

namespace Bug9573;

class MyClass {

/** @var list<positive-int> */
public array $array;

/**
* @param positive-int $count
*/
public function __construct(int $count) {
$this->array = range(1, $count);
}

}
61 changes: 61 additions & 0 deletions tests/PHPStan/Analyser/data/range-int-range.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

namespace RangeIntRange;

use function PHPStan\Testing\assertType;

class Foo
{

/**
* @param int<0,max> $a
* @param int<0,max> $b
*/
public function zeroToMax(
int $a,
int $b
): void
{
assertType('list<int<0, max>>', range($a, $b));
}

/**
* @param int<2,10> $a
* @param int<5,20> $b
*/
public function twoToTwenty(
int $a,
int $b
): void
{
assertType('list<int<2, 20>>', range($a, $b));
}

/**
* @param int<10,30> $a
* @param int<5,20> $b
*/
public function fifteenTo5(
int $a,
int $b
): void
{
assertType('list<int<5, 30>>', range($a, $b));
}

public function knownRange(
): void
{
$a = 5;
$b = 10;
assertType('array{5, 6, 7, 8, 9, 10}', range($a, $b));
}

public function knownLargeRange(
): void
{
$a = 5;
$b = 100;
assertType('non-empty-list<int<5, 100>>', range($a, $b));
}
}

0 comments on commit 9d3eba2

Please sign in to comment.