132
132
use PHPStan \Type \Constant \ConstantArrayTypeBuilder ;
133
133
use PHPStan \Type \Constant \ConstantBooleanType ;
134
134
use PHPStan \Type \Constant \ConstantIntegerType ;
135
- use PHPStan \Type \Constant \ConstantStringType ;
136
135
use PHPStan \Type \ErrorType ;
137
136
use PHPStan \Type \FileTypeMapper ;
137
+ use PHPStan \Type \GeneralizePrecision ;
138
138
use PHPStan \Type \Generic \GenericClassStringType ;
139
139
use PHPStan \Type \Generic \TemplateTypeHelper ;
140
140
use PHPStan \Type \Generic \TemplateTypeMap ;
@@ -1916,8 +1916,8 @@ function (MutatingScope $scope) use ($expr, $nodeCallback, $context): Expression
1916
1916
foreach ($ callArgs as $ callArg ) {
1917
1917
$ callArgType = $ scope ->getType ($ callArg ->value );
1918
1918
if ($ callArg ->unpack ) {
1919
- if ($ callArgType instanceof ConstantArrayType ) {
1920
- $ iterableValueTypes = $ callArgType ->getValueTypes ();
1919
+ if (count ( $ callArgType-> getConstantArrays ()) === 1 ) {
1920
+ $ iterableValueTypes = $ callArgType ->getConstantArrays ()[ 0 ]-> getValueTypes ();
1921
1921
} else {
1922
1922
$ iterableValueTypes = [$ callArgType ->getIterableValueType ()];
1923
1923
$ nonConstantArrayWasUnpacked = true ;
@@ -1960,7 +1960,7 @@ static function (?Type $offsetType, Type $valueType, bool $optional) use (&$arra
1960
1960
$ valueTypes = $ constantArray ->getValueTypes ();
1961
1961
foreach ($ keyTypes as $ k => $ keyType ) {
1962
1962
$ arrayTypeBuilder ->setOffsetValueType (
1963
- $ keyType instanceof ConstantStringType ? $ keyType : null ,
1963
+ count ( $ keyType-> getConstantStrings ()) === 1 ? $ keyType-> getConstantStrings ()[ 0 ] : null ,
1964
1964
$ valueTypes [$ k ],
1965
1965
$ constantArray ->isOptionalKey ($ k ),
1966
1966
);
@@ -1969,10 +1969,11 @@ static function (?Type $offsetType, Type $valueType, bool $optional) use (&$arra
1969
1969
1970
1970
$ constantArray = $ arrayTypeBuilder ->getArray ();
1971
1971
1972
- if ($ constantArray instanceof ConstantArrayType && $ nonConstantArrayWasUnpacked ) {
1972
+ if ($ constantArray ->isConstantArray ()->yes () && $ nonConstantArrayWasUnpacked ) {
1973
+ $ array = new ArrayType ($ constantArray ->generalize (GeneralizePrecision::lessSpecific ())->getIterableKeyType (), $ constantArray ->getIterableValueType ());
1973
1974
$ constantArray = $ constantArray ->isIterableAtLeastOnce ()->yes ()
1974
- ? TypeCombinator::intersect ($ constantArray -> generalizeKeys () , new NonEmptyArrayType ())
1975
- : $ constantArray -> generalizeKeys () ;
1975
+ ? TypeCombinator::intersect ($ array , new NonEmptyArrayType ())
1976
+ : $ array ;
1976
1977
}
1977
1978
1978
1979
$ newArrayTypes [] = $ constantArray ;
@@ -2202,27 +2203,37 @@ static function (?Type $offsetType, Type $valueType, bool $optional) use (&$arra
2202
2203
$ nativeThisType = $ nativeArgType ;
2203
2204
}
2204
2205
}
2205
- $ scopeClass = 'static ' ;
2206
+ $ scopeClasses = [ 'static ' ] ;
2206
2207
if (isset ($ expr ->getArgs ()[2 ])) {
2207
2208
$ argValue = $ expr ->getArgs ()[2 ]->value ;
2208
2209
$ argValueType = $ scope ->getType ($ argValue );
2209
2210
2211
+ $ scopeClasses = [];
2210
2212
$ directClassNames = $ argValueType ->getObjectClassNames ();
2211
- if (count ($ directClassNames ) === 1 ) {
2212
- $ scopeClass = $ directClassNames [0 ];
2213
- $ thisType = new ObjectType ($ scopeClass );
2214
- } elseif ($ argValueType instanceof ConstantStringType) {
2215
- $ scopeClass = $ argValueType ->getValue ();
2216
- $ thisType = new ObjectType ($ scopeClass );
2213
+ if (count ($ directClassNames ) > 0 ) {
2214
+ $ scopeClasses = $ directClassNames ;
2215
+ $ thisTypes = [];
2216
+ foreach ($ directClassNames as $ directClassName ) {
2217
+ $ thisTypes [] = new ObjectType ($ directClassName );
2218
+ }
2219
+ $ thisType = TypeCombinator::union (...$ thisTypes );
2220
+ } elseif (count ($ argValueType ->getConstantStrings ()) > 0 ) {
2221
+ $ thisTypes = [];
2222
+ foreach ($ argValueType ->getConstantStrings () as $ constantString ) {
2223
+ $ scopeClasses [] = $ constantString ->getValue ();
2224
+ $ thisTypes [] = new ObjectType ($ constantString ->getValue ());
2225
+ }
2226
+
2227
+ $ thisType = TypeCombinator::union (...$ thisTypes );
2217
2228
} elseif ($ argValueType instanceof GenericClassStringType) {
2218
2229
$ genericClassNames = $ argValueType ->getGenericType ()->getObjectClassNames ();
2219
- if (count ($ genericClassNames ) === 1 ) {
2220
- $ scopeClass = $ genericClassNames[ 0 ] ;
2230
+ if (count ($ genericClassNames ) > 0 ) {
2231
+ $ scopeClasses = $ genericClassNames ;
2221
2232
$ thisType = $ argValueType ->getGenericType ();
2222
2233
}
2223
2234
}
2224
2235
}
2225
- $ closureBindScope = $ scope ->enterClosureBind ($ thisType , $ nativeThisType , $ scopeClass );
2236
+ $ closureBindScope = $ scope ->enterClosureBind ($ thisType , $ nativeThisType , $ scopeClasses );
2226
2237
}
2227
2238
} else {
2228
2239
$ throwPoints [] = ThrowPoint::createImplicit ($ scope , $ expr );
0 commit comments