Skip to content

Commit 0d7189c

Browse files
committed
Merge branch '1.5.x' into 1.6.x
2 parents 35f0696 + f091c56 commit 0d7189c

File tree

4 files changed

+65
-6
lines changed

4 files changed

+65
-6
lines changed

src/Reflection/GenericParametersAcceptorResolver.php

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@
55
use PHPStan\Type\ErrorType;
66
use PHPStan\Type\Generic\TemplateTypeMap;
77
use PHPStan\Type\Type;
8+
use PHPStan\Type\TypeCombinator;
9+
use function array_key_exists;
810
use function array_merge;
11+
use function count;
12+
use function is_int;
913

1014
class GenericParametersAcceptorResolver
1115
{
@@ -19,15 +23,38 @@ public static function resolve(array $argTypes, ParametersAcceptor $parametersAc
1923
$typeMap = TemplateTypeMap::createEmpty();
2024
$passedArgs = [];
2125

22-
foreach ($parametersAcceptor->getParameters() as $i => $param) {
23-
if (isset($argTypes[$i])) {
24-
$argType = $argTypes[$i];
25-
} elseif (isset($argTypes[$param->getName()])) {
26-
$argType = $argTypes[$param->getName()];
26+
$parameters = $parametersAcceptor->getParameters();
27+
$namedArgTypes = [];
28+
foreach ($argTypes as $i => $argType) {
29+
if (is_int($i)) {
30+
if (isset($parameters[$i])) {
31+
$namedArgTypes[$parameters[$i]->getName()] = $argType;
32+
continue;
33+
}
34+
if (count($parameters) > 0) {
35+
$lastParameter = $parameters[count($parameters) - 1];
36+
if ($lastParameter->isVariadic()) {
37+
$parameterName = $lastParameter->getName();
38+
if (array_key_exists($parameterName, $namedArgTypes)) {
39+
$namedArgTypes[$parameterName] = TypeCombinator::union($namedArgTypes[$parameterName], $argType);
40+
continue;
41+
}
42+
$namedArgTypes[$parameterName] = $argType;
43+
}
44+
}
45+
continue;
46+
}
47+
48+
$namedArgTypes[$i] = $argType;
49+
}
50+
51+
foreach ($parametersAcceptor->getParameters() as $param) {
52+
if (isset($namedArgTypes[$param->getName()])) {
53+
$argType = $namedArgTypes[$param->getName()];
2754
} elseif ($param->getDefaultValue() !== null) {
2855
$argType = $param->getDefaultValue();
2956
} else {
30-
break;
57+
continue;
3158
}
3259

3360
$paramType = $param->getType();

tests/PHPStan/Analyser/AnalyserIntegrationTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,12 @@ public function testBug6192(): void
715715
$this->assertNoErrors($errors);
716716
}
717717

718+
public function testBug7068(): void
719+
{
720+
$errors = $this->runAnalyse(__DIR__ . '/data/bug-7068.php');
721+
$this->assertNoErrors($errors);
722+
}
723+
718724
/**
719725
* @param string[]|null $allAnalysedFiles
720726
* @return Error[]

tests/PHPStan/Analyser/NodeScopeResolverTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -881,6 +881,7 @@ public function dataFileAsserts(): iterable
881881

882882
require_once __DIR__ . '/data/constant-phpdoc-type.php';
883883
yield from $this->gatherAssertTypes(__DIR__ . '/data/constant-phpdoc-type.php');
884+
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7068.php');
884885
}
885886

886887
/**
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
namespace Bug7068;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
class Foo
8+
{
9+
10+
/**
11+
* @template T
12+
* @param array<T> ...$arrays
13+
* @return array<T>
14+
*/
15+
function merge(array ...$arrays): array {
16+
return array_merge(...$arrays);
17+
}
18+
19+
public function doFoo(): void
20+
{
21+
assertType('array<int>', $this->merge([1, 2], [3, 4], [5]));
22+
assertType('array<int|string>', $this->merge([1, 2], ['foo', 'bar']));
23+
}
24+
25+
}

0 commit comments

Comments
 (0)