19
19
use PHPStan \Type \TypeCombinator ;
20
20
use PHPStan \Type \TypeUtils ;
21
21
use function array_map ;
22
+ use function array_reduce ;
22
23
use function array_slice ;
23
24
use function count ;
24
25
@@ -55,19 +56,18 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
55
56
)->getReturnType ();
56
57
} elseif ($ callableIsNull ) {
57
58
$ arrayBuilder = ConstantArrayTypeBuilder::createEmpty ();
58
- $ argIterableValueTypes = [];
59
- $ addNull = false ;
59
+ $ argTypes = [];
60
+ $ areAllSameSize = true ;
60
61
$ expectedSize = null ;
61
62
foreach (array_slice ($ functionCall ->getArgs (), 1 ) as $ index => $ arg ) {
62
- $ argType = $ scope ->getType ($ arg ->value );
63
- $ argIterableValueTypes [$ index ] = $ argType ->getIterableValueType ();
64
- if ($ addNull ) {
63
+ $ argTypes [$ index ] = $ argType = $ scope ->getType ($ arg ->value );
64
+ if (!$ areAllSameSize || $ numArgs === 2 ) {
65
65
continue ;
66
66
}
67
67
68
68
$ arraySizes = $ argType ->getArraySize ()->getConstantScalarValues ();
69
69
if ($ arraySizes === []) {
70
- $ addNull = true ;
70
+ $ areAllSameSize = false ;
71
71
continue ;
72
72
}
73
73
@@ -77,12 +77,30 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
77
77
continue ;
78
78
}
79
79
80
- $ addNull = true ;
81
- break ;
80
+ $ areAllSameSize = false ;
81
+ continue 2 ;
82
82
}
83
83
}
84
84
85
- foreach ($ argIterableValueTypes as $ index => $ offsetValueType ) {
85
+ if (!$ areAllSameSize ) {
86
+ $ firstArr = $ functionCall ->getArgs ()[1 ]->value ;
87
+ $ identities = [];
88
+ foreach (array_slice ($ functionCall ->getArgs (), 2 ) as $ arg ) {
89
+ $ identities [] = new Node \Expr \BinaryOp \Identical ($ firstArr , $ arg ->value );
90
+ }
91
+
92
+ $ and = array_reduce (
93
+ $ identities ,
94
+ static fn (Node \Expr $ a , Node \Expr $ b ) => new Node \Expr \BinaryOp \BooleanAnd ($ a , $ b ),
95
+ new Node \Expr \ConstFetch (new Node \Name ('true ' )),
96
+ );
97
+ $ areAllSameSize = $ scope ->getType ($ and )->isTrue ()->yes ();
98
+ }
99
+
100
+ $ addNull = !$ areAllSameSize ;
101
+
102
+ foreach ($ argTypes as $ index => $ argType ) {
103
+ $ offsetValueType = $ argType ->getIterableValueType ();
86
104
if ($ addNull ) {
87
105
$ offsetValueType = TypeCombinator::addNull ($ offsetValueType );
88
106
}
0 commit comments