Skip to content

Commit 7d9ae90

Browse files
committed
Merge remote-tracking branch 'origin/1.12.x' into 2.1.x
2 parents 8db230f + 8368b0c commit 7d9ae90

File tree

6 files changed

+94
-0
lines changed

6 files changed

+94
-0
lines changed

phpstan-baseline.neon

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1182,6 +1182,12 @@ parameters:
11821182
count: 3
11831183
path: src/Type/Generic/TemplateIntersectionType.php
11841184

1185+
-
1186+
message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#'
1187+
identifier: phpstanApi.instanceofType
1188+
count: 3
1189+
path: src/Type/Generic/TemplateIterableType.php
1190+
11851191
-
11861192
message: '#^Doing instanceof PHPStan\\Type\\IntersectionType is error\-prone and deprecated\.$#'
11871193
identifier: phpstanApi.instanceofType
@@ -1272,6 +1278,12 @@ parameters:
12721278
count: 1
12731279
path: src/Type/Generic/TemplateTypeFactory.php
12741280

1281+
-
1282+
message: '#^Doing instanceof PHPStan\\Type\\IterableType is error\-prone and deprecated\. Use Type\:\:isIterable\(\) instead\.$#'
1283+
identifier: phpstanApi.instanceofType
1284+
count: 1
1285+
path: src/Type/Generic/TemplateTypeFactory.php
1286+
12751287
-
12761288
message: '#^Doing instanceof PHPStan\\Type\\ObjectShapeType is error\-prone and deprecated\. Use Type\:\:isObject\(\) and Type\:\:hasProperty\(\) instead\.$#'
12771289
identifier: phpstanApi.instanceofType

src/Rules/Generics/TemplateTypeCheck.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use PHPStan\Type\Generic\TemplateTypeScope;
2424
use PHPStan\Type\IntegerType;
2525
use PHPStan\Type\IntersectionType;
26+
use PHPStan\Type\IterableType;
2627
use PHPStan\Type\KeyOfType;
2728
use PHPStan\Type\MixedType;
2829
use PHPStan\Type\ObjectShapeType;
@@ -126,6 +127,7 @@ public function check(
126127
&& $boundTypeClass !== ObjectShapeType::class
127128
&& $boundTypeClass !== GenericObjectType::class
128129
&& $boundTypeClass !== KeyOfType::class
130+
&& $boundTypeClass !== IterableType::class
129131
&& !$boundType instanceof UnionType
130132
&& !$boundType instanceof IntersectionType
131133
&& !$boundType instanceof TemplateType
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Type\Generic;
4+
5+
use PHPStan\Type\IterableType;
6+
use PHPStan\Type\Traits\UndecidedComparisonCompoundTypeTrait;
7+
use PHPStan\Type\Type;
8+
9+
/** @api */
10+
final class TemplateIterableType extends IterableType implements TemplateType
11+
{
12+
13+
/** @use TemplateTypeTrait<IterableType> */
14+
use TemplateTypeTrait;
15+
use UndecidedComparisonCompoundTypeTrait;
16+
17+
/**
18+
* @param non-empty-string $name
19+
*/
20+
public function __construct(
21+
TemplateTypeScope $scope,
22+
TemplateTypeStrategy $templateTypeStrategy,
23+
TemplateTypeVariance $templateTypeVariance,
24+
string $name,
25+
IterableType $bound,
26+
?Type $default,
27+
)
28+
{
29+
parent::__construct($bound->getKeyType(), $bound->getItemType());
30+
$this->scope = $scope;
31+
$this->strategy = $templateTypeStrategy;
32+
$this->variance = $templateTypeVariance;
33+
$this->name = $name;
34+
$this->bound = $bound;
35+
$this->default = $default;
36+
}
37+
38+
}

src/Type/Generic/TemplateTypeFactory.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use PHPStan\Type\FloatType;
1313
use PHPStan\Type\IntegerType;
1414
use PHPStan\Type\IntersectionType;
15+
use PHPStan\Type\IterableType;
1516
use PHPStan\Type\KeyOfType;
1617
use PHPStan\Type\MixedType;
1718
use PHPStan\Type\ObjectShapeType;
@@ -107,6 +108,10 @@ public static function create(TemplateTypeScope $scope, string $name, ?Type $bou
107108
return new TemplateKeyOfType($scope, $strategy, $variance, $name, $bound, $default);
108109
}
109110

111+
if ($bound instanceof IterableType && ($boundClass === IterableType::class || $bound instanceof TemplateType)) {
112+
return new TemplateIterableType($scope, $strategy, $variance, $name, $bound, $default);
113+
}
114+
110115
return new TemplateMixedType($scope, $strategy, $variance, $name, new MixedType(true), $default);
111116
}
112117

tests/PHPStan/Analyser/AnalyserIntegrationTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1520,6 +1520,12 @@ public function testBug11511(): void
15201520
$this->assertSame('Access to an undefined property object::$bar.', $errors[0]->getMessage());
15211521
}
15221522

1523+
public function testBug12214(): void
1524+
{
1525+
$errors = $this->runAnalyse(__DIR__ . '/data/bug-12214.php');
1526+
$this->assertNoErrors($errors);
1527+
}
1528+
15231529
public function testBug11640(): void
15241530
{
15251531
$errors = $this->runAnalyse(__DIR__ . '/data/bug-11640.php');
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
namespace Bug12214;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
/**
8+
* @param iterable<array-key, mixed> $test
9+
*/
10+
function test_iterable(iterable $test): void
11+
{
12+
assertType('iterable<(int|string), mixed>', $test);
13+
}
14+
15+
/**
16+
* @template T of array<array-key, mixed>
17+
* @param T $test
18+
*/
19+
function test_array(array $test): void
20+
{
21+
assertType('T of array (function Bug12214\test_array(), argument)', $test);
22+
}
23+
24+
/**
25+
* @template T of iterable<array-key, mixed>
26+
* @param T $test
27+
*/
28+
function test_generic_iterable(iterable $test): void
29+
{
30+
assertType('T of iterable<(int|string), mixed> (function Bug12214\test_generic_iterable(), argument)', $test);
31+
}

0 commit comments

Comments
 (0)