@@ -1446,45 +1446,50 @@ private function callOperatorTypeSpecifyingExtensions(Expr\BinaryOp $expr, Type
14461446 */
14471447 private function resolveCommonMath (Expr \BinaryOp $ expr , Type $ leftType , Type $ rightType ): Type
14481448 {
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 ();
14521452
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) {
14541462 return $ this ->integerRangeMath (
1455- $ leftType ,
1463+ $ leftNumberType ,
14561464 $ expr ,
1457- $ rightType ,
1465+ $ rightNumberType ,
14581466 );
1459- } elseif ($ leftType instanceof UnionType) {
1460-
1467+ } elseif ($ leftNumberType instanceof UnionType) {
14611468 $ unionParts = [];
14621469
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 );
14661474 } else {
1467- $ unionParts [] = $ type ;
1475+ $ unionParts [] = $ numberType ;
14681476 }
14691477 }
14701478
14711479 $ union = TypeCombinator::union (...$ unionParts );
1472- if ($ leftType instanceof BenevolentUnionType) {
1480+ if ($ leftNumberType instanceof BenevolentUnionType) {
14731481 return TypeUtils::toBenevolentUnion ($ union )->toNumber ();
14741482 }
14751483
14761484 return $ union ->toNumber ();
14771485 }
1478-
1479- return $ this ->integerRangeMath ($ leftType , $ expr , $ rightType );
14801486 }
14811487
14821488 $ specifiedTypes = $ this ->callOperatorTypeSpecifyingExtensions ($ expr , $ leftType , $ rightType );
14831489 if ($ specifiedTypes !== null ) {
14841490 return $ specifiedTypes ;
14851491 }
14861492
1487- $ types = TypeCombinator::union ($ leftType , $ rightType );
14881493 if (
14891494 $ leftType ->isArray ()->yes ()
14901495 || $ rightType ->isArray ()->yes ()
@@ -1493,8 +1498,6 @@ private function resolveCommonMath(Expr\BinaryOp $expr, Type $leftType, Type $ri
14931498 return new ErrorType ();
14941499 }
14951500
1496- $ leftNumberType = $ leftType ->toNumber ();
1497- $ rightNumberType = $ rightType ->toNumber ();
14981501 if ($ leftNumberType instanceof ErrorType || $ rightNumberType instanceof ErrorType) {
14991502 return new ErrorType ();
15001503 }
@@ -1531,7 +1534,6 @@ private function resolveCommonMath(Expr\BinaryOp $expr, Type $leftType, Type $ri
15311534 /**
15321535 * @param ConstantIntegerType|IntegerRangeType $range
15331536 * @param BinaryOp\Div|BinaryOp\Minus|BinaryOp\Mul|BinaryOp\Plus $node
1534- * @param IntegerRangeType|ConstantIntegerType|UnionType $operand
15351537 */
15361538 private function integerRangeMath (Type $ range , BinaryOp $ node , Type $ operand ): Type
15371539 {
@@ -1548,8 +1550,9 @@ private function integerRangeMath(Type $range, BinaryOp $node, Type $operand): T
15481550 $ unionParts = [];
15491551
15501552 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 );
15531556 } else {
15541557 $ unionParts [] = $ type ->toNumber ();
15551558 }
@@ -1563,12 +1566,15 @@ private function integerRangeMath(Type $range, BinaryOp $node, Type $operand): T
15631566 return $ union ->toNumber ();
15641567 }
15651568
1569+ $ operand = $ operand ->toNumber ();
15661570 if ($ operand instanceof IntegerRangeType) {
15671571 $ operandMin = $ operand ->getMin ();
15681572 $ operandMax = $ operand ->getMax ();
1569- } else {
1573+ } elseif ( $ operand instanceof ConstantIntegerType) {
15701574 $ operandMin = $ operand ->getValue ();
15711575 $ operandMax = $ operand ->getValue ();
1576+ } else {
1577+ return $ operand ;
15721578 }
15731579
15741580 if ($ node instanceof BinaryOp \Plus) {
0 commit comments