Skip to content

Commit dde8da5

Browse files
authored
Merge branch refs/heads/1.12.x into 2.1.x
2 parents 12185ab + 5920c98 commit dde8da5

File tree

3 files changed

+82
-2
lines changed

3 files changed

+82
-2
lines changed

src/Type/CallableType.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use PHPStan\Reflection\Native\NativeParameterReflection;
2020
use PHPStan\Reflection\ParameterReflection;
2121
use PHPStan\Reflection\ParametersAcceptor;
22+
use PHPStan\Reflection\ParametersAcceptorSelector;
2223
use PHPStan\Reflection\PassedByReference;
2324
use PHPStan\Reflection\Php\DummyParameter;
2425
use PHPStan\ShouldNotHappenException;
@@ -388,10 +389,12 @@ public function inferTemplateTypes(Type $receivedType): TemplateTypeMap
388389

389390
private function inferTemplateTypesOnParametersAcceptor(ParametersAcceptor $parametersAcceptor): TemplateTypeMap
390391
{
391-
$typeMap = TemplateTypeMap::createEmpty();
392+
$parameterTypes = array_map(static fn ($parameter) => $parameter->getType(), $this->getParameters());
393+
$parametersAcceptor = ParametersAcceptorSelector::selectFromTypes($parameterTypes, [$parametersAcceptor], false);
392394
$args = $parametersAcceptor->getParameters();
393395
$returnType = $parametersAcceptor->getReturnType();
394396

397+
$typeMap = TemplateTypeMap::createEmpty();
395398
foreach ($this->getParameters() as $i => $param) {
396399
$paramType = $param->getType();
397400
if (isset($args[$i])) {

src/Type/ClosureType.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
use PHPStan\Reflection\Native\NativeParameterReflection;
2525
use PHPStan\Reflection\ParameterReflection;
2626
use PHPStan\Reflection\ParametersAcceptor;
27+
use PHPStan\Reflection\ParametersAcceptorSelector;
2728
use PHPStan\Reflection\PassedByReference;
2829
use PHPStan\Reflection\Php\ClosureCallUnresolvedMethodPrototypeReflection;
2930
use PHPStan\Reflection\Php\DummyParameter;
@@ -523,10 +524,12 @@ public function inferTemplateTypes(Type $receivedType): TemplateTypeMap
523524

524525
private function inferTemplateTypesOnParametersAcceptor(ParametersAcceptor $parametersAcceptor): TemplateTypeMap
525526
{
526-
$typeMap = TemplateTypeMap::createEmpty();
527+
$parameterTypes = array_map(static fn ($parameter) => $parameter->getType(), $this->getParameters());
528+
$parametersAcceptor = ParametersAcceptorSelector::selectFromTypes($parameterTypes, [$parametersAcceptor], false);
527529
$args = $parametersAcceptor->getParameters();
528530
$returnType = $parametersAcceptor->getReturnType();
529531

532+
$typeMap = TemplateTypeMap::createEmpty();
530533
foreach ($this->getParameters() as $i => $param) {
531534
$paramType = $param->getType();
532535
if (isset($args[$i])) {
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Bug12691;
4+
5+
use Closure;
6+
use function PHPStan\Testing\assertType;
7+
8+
/**
9+
* @template T
10+
*/
11+
class Option
12+
{
13+
/**
14+
* @param T $value
15+
*/
16+
public function __construct(
17+
public mixed $value,
18+
) {
19+
}
20+
21+
/**
22+
* @template S
23+
* @param callable(T): S $callable
24+
* @return self<S>
25+
*/
26+
public function map($callable): self
27+
{
28+
return new self($callable($this->value));
29+
}
30+
31+
/**
32+
* @template S
33+
* @param Closure(T): S $callable
34+
* @return self<S>
35+
*/
36+
public function mapClosure($callable): self
37+
{
38+
return new self($callable($this->value));
39+
}
40+
}
41+
42+
/**
43+
* @param Option<non-empty-array<int>> $ints
44+
*/
45+
function doFoo(Option $ints): void {
46+
assertType('Bug12691\\Option<non-empty-list<int>>', $ints->map(array_values(...)));
47+
assertType('Bug12691\\Option<non-empty-list<int>>', $ints->map('array_values'));
48+
assertType('Bug12691\\Option<non-empty-list<int>>', $ints->map(static fn ($value) => array_values($value)));
49+
};
50+
51+
/**
52+
* @param Option<non-empty-array<int>> $ints
53+
*/
54+
function doFooClosure(Option $ints): void {
55+
assertType('Bug12691\\Option<non-empty-list<int>>', $ints->mapClosure(array_values(...)));
56+
assertType('Bug12691\\Option<non-empty-list<int>>', $ints->mapClosure(static fn ($value) => array_values($value)));
57+
};
58+
59+
/**
60+
* @template T
61+
* @param array<T> $a
62+
* @return ($a is non-empty-array ? non-empty-list<T> : list<T>)
63+
*/
64+
function myArrayValues(array $a): array {
65+
66+
}
67+
68+
/**
69+
* @param Option<non-empty-array<int>> $ints
70+
*/
71+
function doBar(Option $ints): void {
72+
assertType('Bug12691\\Option<non-empty-list<int>>', $ints->mapClosure(myArrayValues(...)));
73+
assertType('Bug12691\\Option<non-empty-list<int>>', $ints->mapClosure(static fn ($value) => myArrayValues($value)));
74+
};

0 commit comments

Comments
 (0)