@@ -1263,6 +1263,58 @@ private function resolveType(Expr $node): Type
12631263 $ leftType = $ this ->getType ($ left );
12641264 $ rightType = $ this ->getType ($ right );
12651265
1266+ if ($ node instanceof Expr \AssignOp \Plus || $ node instanceof Expr \BinaryOp \Plus) {
1267+ $ leftConstantArrays = TypeUtils::getConstantArrays ($ leftType );
1268+ $ rightConstantArrays = TypeUtils::getConstantArrays ($ rightType );
1269+
1270+ if (count ($ leftConstantArrays ) > 0 && count ($ rightConstantArrays ) > 0 ) {
1271+ $ resultTypes = [];
1272+ foreach ($ rightConstantArrays as $ rightConstantArray ) {
1273+ foreach ($ leftConstantArrays as $ leftConstantArray ) {
1274+ $ newArrayBuilder = ConstantArrayTypeBuilder::createFromConstantArray ($ rightConstantArray );
1275+ foreach ($ leftConstantArray ->getKeyTypes () as $ leftKeyType ) {
1276+ $ newArrayBuilder ->setOffsetValueType (
1277+ $ leftKeyType ,
1278+ $ leftConstantArray ->getOffsetValueType ($ leftKeyType )
1279+ );
1280+ }
1281+ $ resultTypes [] = $ newArrayBuilder ->getArray ();
1282+ }
1283+ }
1284+
1285+ return TypeCombinator::union (...$ resultTypes );
1286+ }
1287+ $ arrayType = new ArrayType (new MixedType (), new MixedType ());
1288+
1289+ if ($ arrayType ->isSuperTypeOf ($ leftType )->yes () && $ arrayType ->isSuperTypeOf ($ rightType )->yes ()) {
1290+ if ($ leftType ->getIterableKeyType ()->equals ($ rightType ->getIterableKeyType ())) {
1291+ // to preserve BenevolentUnionType
1292+ $ keyType = $ leftType ->getIterableKeyType ();
1293+ } else {
1294+ $ keyTypes = [];
1295+ foreach ([
1296+ $ leftType ->getIterableKeyType (),
1297+ $ rightType ->getIterableKeyType (),
1298+ ] as $ keyType ) {
1299+ $ keyTypes [] = $ keyType ;
1300+ }
1301+ $ keyType = TypeCombinator::union (...$ keyTypes );
1302+ }
1303+ return new ArrayType (
1304+ $ keyType ,
1305+ TypeCombinator::union ($ leftType ->getIterableValueType (), $ rightType ->getIterableValueType ())
1306+ );
1307+ }
1308+
1309+ if ($ leftType instanceof MixedType && $ rightType instanceof MixedType) {
1310+ return new BenevolentUnionType ([
1311+ new FloatType (),
1312+ new IntegerType (),
1313+ new ArrayType (new MixedType (), new MixedType ()),
1314+ ]);
1315+ }
1316+ }
1317+
12661318 if (($ leftType instanceof IntegerRangeType || $ leftType instanceof ConstantIntegerType || $ leftType instanceof UnionType) &&
12671319 ($ rightType instanceof IntegerRangeType || $ rightType instanceof ConstantIntegerType || $ rightType instanceof UnionType) &&
12681320 !($ node instanceof Node \Expr \BinaryOp \Pow || $ node instanceof Node \Expr \AssignOp \Pow)) {
@@ -1321,58 +1373,6 @@ private function resolveType(Expr $node): Type
13211373 }
13221374 }
13231375
1324- if ($ node instanceof Expr \AssignOp \Plus || $ node instanceof Expr \BinaryOp \Plus) {
1325- $ leftConstantArrays = TypeUtils::getConstantArrays ($ leftType );
1326- $ rightConstantArrays = TypeUtils::getConstantArrays ($ rightType );
1327-
1328- if (count ($ leftConstantArrays ) > 0 && count ($ rightConstantArrays ) > 0 ) {
1329- $ resultTypes = [];
1330- foreach ($ rightConstantArrays as $ rightConstantArray ) {
1331- foreach ($ leftConstantArrays as $ leftConstantArray ) {
1332- $ newArrayBuilder = ConstantArrayTypeBuilder::createFromConstantArray ($ rightConstantArray );
1333- foreach ($ leftConstantArray ->getKeyTypes () as $ leftKeyType ) {
1334- $ newArrayBuilder ->setOffsetValueType (
1335- $ leftKeyType ,
1336- $ leftConstantArray ->getOffsetValueType ($ leftKeyType )
1337- );
1338- }
1339- $ resultTypes [] = $ newArrayBuilder ->getArray ();
1340- }
1341- }
1342-
1343- return TypeCombinator::union (...$ resultTypes );
1344- }
1345- $ arrayType = new ArrayType (new MixedType (), new MixedType ());
1346-
1347- if ($ arrayType ->isSuperTypeOf ($ leftType )->yes () && $ arrayType ->isSuperTypeOf ($ rightType )->yes ()) {
1348- if ($ leftType ->getIterableKeyType ()->equals ($ rightType ->getIterableKeyType ())) {
1349- // to preserve BenevolentUnionType
1350- $ keyType = $ leftType ->getIterableKeyType ();
1351- } else {
1352- $ keyTypes = [];
1353- foreach ([
1354- $ leftType ->getIterableKeyType (),
1355- $ rightType ->getIterableKeyType (),
1356- ] as $ keyType ) {
1357- $ keyTypes [] = $ keyType ;
1358- }
1359- $ keyType = TypeCombinator::union (...$ keyTypes );
1360- }
1361- return new ArrayType (
1362- $ keyType ,
1363- TypeCombinator::union ($ leftType ->getIterableValueType (), $ rightType ->getIterableValueType ())
1364- );
1365- }
1366-
1367- if ($ leftType instanceof MixedType && $ rightType instanceof MixedType) {
1368- return new BenevolentUnionType ([
1369- new FloatType (),
1370- new IntegerType (),
1371- new ArrayType (new MixedType (), new MixedType ()),
1372- ]);
1373- }
1374- }
1375-
13761376 $ types = TypeCombinator::union ($ leftType , $ rightType );
13771377 if (
13781378 $ leftType instanceof ArrayType
0 commit comments