99use PHPStan \Type \Accessory \NonEmptyArrayType ;
1010use PHPStan \Type \ArrayType ;
1111use PHPStan \Type \Constant \ConstantArrayTypeBuilder ;
12+ use PHPStan \Type \Constant \ConstantIntegerType ;
1213use PHPStan \Type \IntegerType ;
1314use PHPStan \Type \MixedType ;
1415use PHPStan \Type \NeverType ;
16+ use PHPStan \Type \NullType ;
1517use PHPStan \Type \Type ;
1618use PHPStan \Type \TypeCombinator ;
1719use PHPStan \Type \TypeUtils ;
@@ -30,23 +32,35 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
3032 return ParametersAcceptorSelector::selectSingle ($ functionReflection ->getVariants ())->getReturnType ();
3133 }
3234
33- $ valueType = new MixedType ( );
35+ $ singleArrayArgument = ! isset ( $ functionCall -> getArgs ()[ 2 ] );
3436 $ callableType = $ scope ->getType ($ functionCall ->getArgs ()[0 ]->value );
37+ $ callableIsNull = (new NullType ())->isSuperTypeOf ($ callableType )->yes ();
38+
3539 if ($ callableType ->isCallable ()->yes ()) {
3640 $ valueType = new NeverType ();
3741 foreach ($ callableType ->getCallableParametersAcceptors ($ scope ) as $ parametersAcceptor ) {
3842 $ valueType = TypeCombinator::union ($ valueType , $ parametersAcceptor ->getReturnType ());
3943 }
44+ } elseif ($ callableIsNull ) {
45+ $ arrayBuilder = ConstantArrayTypeBuilder::createEmpty ();
46+ foreach (array_slice ($ functionCall ->getArgs (), 1 ) as $ index => $ arg ) {
47+ $ arrayBuilder ->setOffsetValueType (
48+ new ConstantIntegerType ($ index ),
49+ $ scope ->getType ($ arg ->value )->getIterableValueType ()
50+ );
51+ }
52+ $ valueType = $ arrayBuilder ->getArray ();
53+ } else {
54+ $ valueType = new MixedType ();
4055 }
4156
42- $ mappedArrayType = new ArrayType (
43- new MixedType (),
44- $ valueType
45- );
4657 $ arrayType = $ scope ->getType ($ functionCall ->getArgs ()[1 ]->value );
47- $ constantArrays = TypeUtils::getConstantArrays ($ arrayType );
4858
49- if (!isset ($ functionCall ->getArgs ()[2 ])) {
59+ if ($ singleArrayArgument ) {
60+ if ($ callableIsNull ) {
61+ return $ arrayType ;
62+ }
63+ $ constantArrays = TypeUtils::getConstantArrays ($ arrayType );
5064 if (count ($ constantArrays ) > 0 ) {
5165 $ arrayTypes = [];
5266 foreach ($ constantArrays as $ constantArray ) {
@@ -66,6 +80,11 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection,
6680 $ arrayType ->getIterableKeyType (),
6781 $ valueType
6882 ), ...TypeUtils::getAccessoryTypes ($ arrayType ));
83+ } else {
84+ $ mappedArrayType = new ArrayType (
85+ new MixedType (),
86+ $ valueType
87+ );
6988 }
7089 } else {
7190 $ mappedArrayType = TypeCombinator::intersect (new ArrayType (
0 commit comments