Skip to content

Commit ae5b8bf

Browse files
github-actions[bot]staabm
authored andcommitted
Fix false positive unresolvable template type on optional variadic params
- When a template type is only used on a variadic parameter and no arguments are passed, it was incorrectly reported as unresolvable - Fixed by inferring NeverType for variadic parameters with no arguments in GenericParametersAcceptorResolver, since an empty variadic means the element type is never - Added regression tests in both rule test and NSRT format Closes phpstan/phpstan#2572
1 parent c381cc0 commit ae5b8bf

4 files changed

Lines changed: 60 additions & 0 deletions

File tree

src/Reflection/GenericParametersAcceptorResolver.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use PHPStan\Type\Generic\TemplateTypeMap;
1111
use PHPStan\Type\Generic\TemplateTypeVarianceMap;
1212
use PHPStan\Type\MixedType;
13+
use PHPStan\Type\NeverType;
1314
use PHPStan\Type\Type;
1415
use PHPStan\Type\TypeCombinator;
1516
use function array_key_exists;
@@ -61,6 +62,8 @@ public static function resolve(array $argTypes, ParametersAcceptor $parametersAc
6162
$argType = $namedArgTypes[$param->getName()];
6263
} elseif ($param->getDefaultValue() !== null) {
6364
$argType = $param->getDefaultValue();
65+
} elseif ($param->isVariadic()) {
66+
$argType = new NeverType();
6467
} else {
6568
continue;
6669
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug2572Nsrt;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
/**
8+
* @template TE
9+
* @template TR
10+
*
11+
* @param TE $elt
12+
* @param TR ...$elts
13+
*
14+
* @return TE|TR
15+
*/
16+
function collect($elt, ...$elts) {
17+
$ret = $elt;
18+
foreach ($elts as $item) {
19+
if (rand(0, 1)) {
20+
$ret = $item;
21+
}
22+
}
23+
return $ret;
24+
}
25+
26+
assertType("'a'", collect("a"));
27+
assertType("'a'|'b'|'c'", collect("a", "b", "c"));

tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2691,6 +2691,11 @@ public function testBug8936(): void
26912691
$this->analyse([__DIR__ . '/data/bug-8936.php'], []);
26922692
}
26932693

2694+
public function testBug2572(): void
2695+
{
2696+
$this->analyse([__DIR__ . '/data/bug-2572.php'], []);
2697+
}
2698+
26942699
public function testDumpFunctions(): void
26952700
{
26962701
$this->analyse([__DIR__ . '/data/dump-functions.php'], [
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug2572;
4+
5+
/**
6+
* @template TE
7+
* @template TR
8+
*
9+
* @param TE $elt
10+
* @param TR ...$elts
11+
*
12+
* @return TE|TR
13+
*/
14+
function collect($elt, ...$elts) {
15+
$ret = $elt;
16+
foreach ($elts as $item) {
17+
if (rand(0, 1)) {
18+
$ret = $item;
19+
}
20+
}
21+
return $ret;
22+
}
23+
24+
echo collect("a");
25+
echo collect("a", "b", "c");

0 commit comments

Comments
 (0)