14
14
use PHPStan \Type \ConstantScalarType ;
15
15
use PHPStan \Type \ConstantTypeHelper ;
16
16
use PHPStan \Type \DynamicFunctionReturnTypeExtension ;
17
- use PHPStan \Type \MixedType ;
18
17
use PHPStan \Type \ObjectType ;
19
18
use PHPStan \Type \Type ;
20
19
use PHPStan \Type \TypeCombinator ;
@@ -59,7 +58,7 @@ public function getTypeFromFunctionCall(
59
58
$ defaultReturnType = ParametersAcceptorSelector::selectSingle ($ functionReflection ->getVariants ())->getReturnType ();
60
59
61
60
if ($ functionReflection ->getName () === 'json_decode ' ) {
62
- $ defaultReturnType = $ this ->narrowTypeForJsonDecode ($ functionCall , $ scope );
61
+ $ defaultReturnType = $ this ->narrowTypeForJsonDecode ($ functionCall , $ scope, $ defaultReturnType );
63
62
}
64
63
65
64
if (!isset ($ functionCall ->getArgs ()[$ argumentPosition ])) {
@@ -74,7 +73,7 @@ public function getTypeFromFunctionCall(
74
73
return $ defaultReturnType ;
75
74
}
76
75
77
- private function narrowTypeForJsonDecode (FuncCall $ funcCall , Scope $ scope ): Type
76
+ private function narrowTypeForJsonDecode (FuncCall $ funcCall , Scope $ scope, Type $ fallbackType ): Type
78
77
{
79
78
$ args = $ funcCall ->getArgs ();
80
79
$ isArrayWithoutStdClass = $ this ->isForceArrayWithoutStdClass ($ funcCall , $ scope );
@@ -86,12 +85,11 @@ private function narrowTypeForJsonDecode(FuncCall $funcCall, Scope $scope): Type
86
85
return $ this ->resolveConstantStringType ($ firstValueType , $ isArrayWithoutStdClass );
87
86
}
88
87
89
- // fallback type
90
- if ($ isArrayWithoutStdClass === true ) {
91
- return new MixedType (true , new ObjectType (stdClass::class));
88
+ if ($ isArrayWithoutStdClass ) {
89
+ return TypeCombinator::remove ($ fallbackType , new ObjectType (stdClass::class));
92
90
}
93
91
94
- return new MixedType ( true ) ;
92
+ return $ fallbackType ;
95
93
}
96
94
97
95
/**
0 commit comments