@@ -1446,45 +1446,50 @@ private function callOperatorTypeSpecifyingExtensions(Expr\BinaryOp $expr, Type
1446
1446
*/
1447
1447
private function resolveCommonMath (Expr \BinaryOp $ expr , Type $ leftType , Type $ rightType ): Type
1448
1448
{
1449
- if (( $ leftType instanceof IntegerRangeType || $ leftType instanceof ConstantIntegerType || $ leftType instanceof UnionType) &&
1450
- ( $ rightType instanceof IntegerRangeType || $ rightType instanceof ConstantIntegerType || $ rightType instanceof UnionType)
1451
- ) {
1449
+ $ types = TypeCombinator:: union ( $ leftType, $ rightType );
1450
+ $ leftNumberType = $ leftType -> toNumber ();
1451
+ $ rightNumberType = $ rightType -> toNumber ();
1452
1452
1453
- if ($ leftType instanceof ConstantIntegerType) {
1453
+ if (
1454
+ !$ types instanceof MixedType
1455
+ && (
1456
+ $ rightNumberType instanceof IntegerRangeType
1457
+ || $ rightNumberType instanceof ConstantIntegerType
1458
+ || $ rightNumberType instanceof UnionType
1459
+ )
1460
+ ) {
1461
+ if ($ leftNumberType instanceof IntegerRangeType || $ leftNumberType instanceof ConstantIntegerType) {
1454
1462
return $ this ->integerRangeMath (
1455
- $ leftType ,
1463
+ $ leftNumberType ,
1456
1464
$ expr ,
1457
- $ rightType ,
1465
+ $ rightNumberType ,
1458
1466
);
1459
- } elseif ($ leftType instanceof UnionType) {
1460
-
1467
+ } elseif ($ leftNumberType instanceof UnionType) {
1461
1468
$ unionParts = [];
1462
1469
1463
- foreach ($ leftType ->getTypes () as $ type ) {
1464
- if ($ type instanceof IntegerRangeType || $ type instanceof ConstantIntegerType) {
1465
- $ unionParts [] = $ this ->integerRangeMath ($ type , $ expr , $ rightType );
1470
+ foreach ($ leftNumberType ->getTypes () as $ type ) {
1471
+ $ numberType = $ type ->toNumber ();
1472
+ if ($ numberType instanceof IntegerRangeType || $ numberType instanceof ConstantIntegerType) {
1473
+ $ unionParts [] = $ this ->integerRangeMath ($ numberType , $ expr , $ rightNumberType );
1466
1474
} else {
1467
- $ unionParts [] = $ type ;
1475
+ $ unionParts [] = $ numberType ;
1468
1476
}
1469
1477
}
1470
1478
1471
1479
$ union = TypeCombinator::union (...$ unionParts );
1472
- if ($ leftType instanceof BenevolentUnionType) {
1480
+ if ($ leftNumberType instanceof BenevolentUnionType) {
1473
1481
return TypeUtils::toBenevolentUnion ($ union )->toNumber ();
1474
1482
}
1475
1483
1476
1484
return $ union ->toNumber ();
1477
1485
}
1478
-
1479
- return $ this ->integerRangeMath ($ leftType , $ expr , $ rightType );
1480
1486
}
1481
1487
1482
1488
$ specifiedTypes = $ this ->callOperatorTypeSpecifyingExtensions ($ expr , $ leftType , $ rightType );
1483
1489
if ($ specifiedTypes !== null ) {
1484
1490
return $ specifiedTypes ;
1485
1491
}
1486
1492
1487
- $ types = TypeCombinator::union ($ leftType , $ rightType );
1488
1493
if (
1489
1494
$ leftType ->isArray ()->yes ()
1490
1495
|| $ rightType ->isArray ()->yes ()
@@ -1493,8 +1498,6 @@ private function resolveCommonMath(Expr\BinaryOp $expr, Type $leftType, Type $ri
1493
1498
return new ErrorType ();
1494
1499
}
1495
1500
1496
- $ leftNumberType = $ leftType ->toNumber ();
1497
- $ rightNumberType = $ rightType ->toNumber ();
1498
1501
if ($ leftNumberType instanceof ErrorType || $ rightNumberType instanceof ErrorType) {
1499
1502
return new ErrorType ();
1500
1503
}
@@ -1531,7 +1534,6 @@ private function resolveCommonMath(Expr\BinaryOp $expr, Type $leftType, Type $ri
1531
1534
/**
1532
1535
* @param ConstantIntegerType|IntegerRangeType $range
1533
1536
* @param BinaryOp\Div|BinaryOp\Minus|BinaryOp\Mul|BinaryOp\Plus $node
1534
- * @param IntegerRangeType|ConstantIntegerType|UnionType $operand
1535
1537
*/
1536
1538
private function integerRangeMath (Type $ range , BinaryOp $ node , Type $ operand ): Type
1537
1539
{
@@ -1548,8 +1550,9 @@ private function integerRangeMath(Type $range, BinaryOp $node, Type $operand): T
1548
1550
$ unionParts = [];
1549
1551
1550
1552
foreach ($ operand ->getTypes () as $ type ) {
1551
- if ($ type instanceof IntegerRangeType || $ type instanceof ConstantIntegerType) {
1552
- $ unionParts [] = $ this ->integerRangeMath ($ range , $ node , $ type );
1553
+ $ numberType = $ type ->toNumber ();
1554
+ if ($ numberType instanceof IntegerRangeType || $ numberType instanceof ConstantIntegerType) {
1555
+ $ unionParts [] = $ this ->integerRangeMath ($ range , $ node , $ numberType );
1553
1556
} else {
1554
1557
$ unionParts [] = $ type ->toNumber ();
1555
1558
}
@@ -1563,12 +1566,15 @@ private function integerRangeMath(Type $range, BinaryOp $node, Type $operand): T
1563
1566
return $ union ->toNumber ();
1564
1567
}
1565
1568
1569
+ $ operand = $ operand ->toNumber ();
1566
1570
if ($ operand instanceof IntegerRangeType) {
1567
1571
$ operandMin = $ operand ->getMin ();
1568
1572
$ operandMax = $ operand ->getMax ();
1569
- } else {
1573
+ } elseif ( $ operand instanceof ConstantIntegerType) {
1570
1574
$ operandMin = $ operand ->getValue ();
1571
1575
$ operandMax = $ operand ->getValue ();
1576
+ } else {
1577
+ return $ operand ;
1572
1578
}
1573
1579
1574
1580
if ($ node instanceof BinaryOp \Plus) {
0 commit comments