@@ -1170,57 +1170,17 @@ public function getPowType(Expr $left, Expr $right, callable $getTypeCallback):
11701170 $ leftType = $ getTypeCallback ($ left );
11711171 $ rightType = $ getTypeCallback ($ right );
11721172
1173- if ($ leftType instanceof MixedType || $ rightType instanceof MixedType) {
1174- return new BenevolentUnionType ([
1175- new FloatType (),
1176- new IntegerType (),
1177- ]);
1173+ $ exponentiatedTyped = $ leftType ->exponentiate ($ rightType );
1174+ if (!$ exponentiatedTyped instanceof ErrorType) {
1175+ return $ exponentiatedTyped ;
11781176 }
11791177
1180- $ object = new ObjectWithoutClassType ();
1181- if (
1182- !$ leftType instanceof NeverType &&
1183- !$ rightType instanceof NeverType &&
1184- (
1185- !$ object ->isSuperTypeOf ($ leftType )->no ()
1186- || !$ object ->isSuperTypeOf ($ rightType )->no ()
1187- )
1188- ) {
1189- return TypeCombinator::union ($ leftType , $ rightType );
1178+ $ extensionSpecified = $ this ->callOperatorTypeSpecifyingExtensions (new BinaryOp \Pow ($ left , $ right ), $ leftType , $ rightType );
1179+ if ($ extensionSpecified !== null ) {
1180+ return $ extensionSpecified ;
11901181 }
11911182
1192- $ leftTypes = TypeUtils::getConstantScalars ($ leftType );
1193- $ rightTypes = TypeUtils::getConstantScalars ($ rightType );
1194- $ leftTypesCount = count ($ leftTypes );
1195- $ rightTypesCount = count ($ rightTypes );
1196- if ($ leftTypesCount > 0 && $ rightTypesCount > 0 ) {
1197- $ resultTypes = [];
1198- $ generalize = $ leftTypesCount * $ rightTypesCount > self ::CALCULATE_SCALARS_LIMIT ;
1199- foreach ($ leftTypes as $ leftTypeInner ) {
1200- foreach ($ rightTypes as $ rightTypeInner ) {
1201- $ leftNumberType = $ leftTypeInner ->toNumber ();
1202- $ rightNumberType = $ rightTypeInner ->toNumber ();
1203-
1204- if ($ leftNumberType instanceof ErrorType || $ rightNumberType instanceof ErrorType) {
1205- return new ErrorType ();
1206- }
1207-
1208- if (!$ leftNumberType instanceof ConstantScalarType || !$ rightNumberType instanceof ConstantScalarType) {
1209- throw new ShouldNotHappenException ();
1210- }
1211-
1212- $ resultType = $ this ->getTypeFromValue ($ leftNumberType ->getValue () ** $ rightNumberType ->getValue ());
1213- if ($ generalize ) {
1214- $ resultType = $ resultType ->generalize (GeneralizePrecision::lessSpecific ());
1215- }
1216- $ resultTypes [] = $ resultType ;
1217- }
1218- }
1219-
1220- return TypeCombinator::union (...$ resultTypes );
1221- }
1222-
1223- return $ this ->resolveCommonMath (new BinaryOp \Pow ($ left , $ right ), $ leftType , $ rightType );
1183+ return new ErrorType ();
12241184 }
12251185
12261186 /**
@@ -1461,14 +1421,33 @@ private function resolveConstantArrayTypeComparison(ConstantArrayType $leftType,
14611421 return $ resultType ->toBoolean ();
14621422 }
14631423
1424+ private function callOperatorTypeSpecifyingExtensions (Expr \BinaryOp $ expr , Type $ leftType , Type $ rightType ): ?Type
1425+ {
1426+ $ operatorSigil = $ expr ->getOperatorSigil ();
1427+ $ operatorTypeSpecifyingExtensions = $ this ->operatorTypeSpecifyingExtensionRegistryProvider ->getRegistry ()->getOperatorTypeSpecifyingExtensions ($ operatorSigil , $ leftType , $ rightType );
1428+
1429+ /** @var Type[] $extensionTypes */
1430+ $ extensionTypes = [];
1431+
1432+ foreach ($ operatorTypeSpecifyingExtensions as $ extension ) {
1433+ $ extensionTypes [] = $ extension ->specifyType ($ operatorSigil , $ leftType , $ rightType );
1434+ }
1435+
1436+ if (count ($ extensionTypes ) > 0 ) {
1437+ return TypeCombinator::union (...$ extensionTypes );
1438+ }
1439+
1440+ return null ;
1441+ }
1442+
14641443 /**
1465- * @param BinaryOp\Plus|BinaryOp\Minus|BinaryOp\Mul|BinaryOp\Pow|BinaryOp\ Div $expr
1444+ * @param BinaryOp\Plus|BinaryOp\Minus|BinaryOp\Mul|BinaryOp\Div $expr
14661445 */
14671446 private function resolveCommonMath (Expr \BinaryOp $ expr , Type $ leftType , Type $ rightType ): Type
14681447 {
14691448 if (($ leftType instanceof IntegerRangeType || $ leftType instanceof ConstantIntegerType || $ leftType instanceof UnionType) &&
1470- ($ rightType instanceof IntegerRangeType || $ rightType instanceof ConstantIntegerType || $ rightType instanceof UnionType) &&
1471- ! $ expr instanceof BinaryOp \Pow ) {
1449+ ($ rightType instanceof IntegerRangeType || $ rightType instanceof ConstantIntegerType || $ rightType instanceof UnionType)
1450+ ) {
14721451
14731452 if ($ leftType instanceof ConstantIntegerType) {
14741453 return $ this ->integerRangeMath (
@@ -1499,18 +1478,9 @@ private function resolveCommonMath(Expr\BinaryOp $expr, Type $leftType, Type $ri
14991478 return $ this ->integerRangeMath ($ leftType , $ expr , $ rightType );
15001479 }
15011480
1502- $ operatorSigil = $ expr ->getOperatorSigil ();
1503- $ operatorTypeSpecifyingExtensions = $ this ->operatorTypeSpecifyingExtensionRegistryProvider ->getRegistry ()->getOperatorTypeSpecifyingExtensions ($ operatorSigil , $ leftType , $ rightType );
1504-
1505- /** @var Type[] $extensionTypes */
1506- $ extensionTypes = [];
1507-
1508- foreach ($ operatorTypeSpecifyingExtensions as $ extension ) {
1509- $ extensionTypes [] = $ extension ->specifyType ($ operatorSigil , $ leftType , $ rightType );
1510- }
1511-
1512- if (count ($ extensionTypes ) > 0 ) {
1513- return TypeCombinator::union (...$ extensionTypes );
1481+ $ specifiedTypes = $ this ->callOperatorTypeSpecifyingExtensions ($ expr , $ leftType , $ rightType );
1482+ if ($ specifiedTypes !== null ) {
1483+ return $ specifiedTypes ;
15141484 }
15151485
15161486 $ types = TypeCombinator::union ($ leftType , $ rightType );
@@ -1538,13 +1508,6 @@ private function resolveCommonMath(Expr\BinaryOp $expr, Type $leftType, Type $ri
15381508 return new FloatType ();
15391509 }
15401510
1541- if ($ expr instanceof Expr \BinaryOp \Pow) {
1542- return new BenevolentUnionType ([
1543- new FloatType (),
1544- new IntegerType (),
1545- ]);
1546- }
1547-
15481511 $ resultType = TypeCombinator::union ($ leftNumberType , $ rightNumberType );
15491512 if ($ expr instanceof Expr \BinaryOp \Div) {
15501513 if ($ types instanceof MixedType || $ resultType ->isInteger ()->yes ()) {
0 commit comments