2
2
3
3
namespace PHPStan \Type \Php ;
4
4
5
+ use PhpParser \Node ;
5
6
use PhpParser \Node \Expr \FuncCall ;
6
7
use PHPStan \Analyser \Scope ;
7
8
use PHPStan \Reflection \FunctionReflection ;
9
+ use PHPStan \Reflection \ParametersAcceptorSelector ;
8
10
use PHPStan \Type \Accessory \AccessoryArrayListType ;
9
11
use PHPStan \Type \Accessory \NonEmptyArrayType ;
10
12
use PHPStan \Type \ArrayType ;
13
15
use PHPStan \Type \DynamicFunctionReturnTypeExtension ;
14
16
use PHPStan \Type \IntegerType ;
15
17
use PHPStan \Type \MixedType ;
16
- use PHPStan \Type \NeverType ;
17
18
use PHPStan \Type \Type ;
18
19
use PHPStan \Type \TypeCombinator ;
19
20
use PHPStan \Type \TypeUtils ;
21
+ use function array_map ;
20
22
use function array_slice ;
21
23
use function count ;
22
24
@@ -38,12 +40,18 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
38
40
$ callableType = $ scope ->getType ($ functionCall ->getArgs ()[0 ]->value );
39
41
$ callableIsNull = $ callableType ->isNull ()->yes ();
40
42
43
+ $ callableParametersAcceptors = null ;
44
+
41
45
if ($ callableType ->isCallable ()->yes ()) {
42
- $ valueTypes = [new NeverType ()];
43
- foreach ($ callableType ->getCallableParametersAcceptors ($ scope ) as $ parametersAcceptor ) {
44
- $ valueTypes [] = $ parametersAcceptor ->getReturnType ();
45
- }
46
- $ valueType = TypeCombinator::union (...$ valueTypes );
46
+ $ callableParametersAcceptors = $ callableType ->getCallableParametersAcceptors ($ scope );
47
+ $ valueType = ParametersAcceptorSelector::selectFromTypes (
48
+ array_map (
49
+ static fn (Node \Arg $ arg ) => $ scope ->getType ($ arg ->value )->getIterableValueType (),
50
+ array_slice ($ functionCall ->getArgs (), 1 ),
51
+ ),
52
+ $ callableParametersAcceptors ,
53
+ false ,
54
+ )->getReturnType ();
47
55
} elseif ($ callableIsNull ) {
48
56
$ arrayBuilder = ConstantArrayTypeBuilder::createEmpty ();
49
57
foreach (array_slice ($ functionCall ->getArgs (), 1 ) as $ index => $ arg ) {
@@ -70,10 +78,17 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
70
78
if ($ totalCount < ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT ) {
71
79
foreach ($ constantArrays as $ constantArray ) {
72
80
$ returnedArrayBuilder = ConstantArrayTypeBuilder::createEmpty ();
81
+ $ valueTypes = $ constantArray ->getValueTypes ();
73
82
foreach ($ constantArray ->getKeyTypes () as $ i => $ keyType ) {
74
83
$ returnedArrayBuilder ->setOffsetValueType (
75
84
$ keyType ,
76
- $ valueType ,
85
+ $ callableParametersAcceptors !== null
86
+ ? ParametersAcceptorSelector::selectFromTypes (
87
+ [$ valueTypes [$ i ]],
88
+ $ callableParametersAcceptors ,
89
+ false ,
90
+ )->getReturnType ()
91
+ : $ valueType ,
77
92
$ constantArray ->isOptionalKey ($ i ),
78
93
);
79
94
}
0 commit comments