6565use PHPStan \Type \Type ;
6666use PHPStan \Type \TypeCombinator ;
6767use PHPStan \Type \TypehintHelper ;
68+ use PHPStan \Type \TypeResult ;
6869use PHPStan \Type \TypeTraverser ;
6970use PHPStan \Type \TypeUtils ;
7071use PHPStan \Type \TypeWithClassName ;
@@ -298,7 +299,7 @@ public function getType(Expr $expr, InitializerExprContext $context): Type
298299 return $ this ->resolveIdenticalType (
299300 $ this ->getType ($ expr ->left , $ context ),
300301 $ this ->getType ($ expr ->right , $ context ),
301- );
302+ )-> type ;
302303 }
303304
304305 if ($ expr instanceof BinaryOp \NotIdentical) {
@@ -309,7 +310,7 @@ public function getType(Expr $expr, InitializerExprContext $context): Type
309310 return $ this ->resolveEqualType (
310311 $ this ->getType ($ expr ->left , $ context ),
311312 $ this ->getType ($ expr ->right , $ context ),
312- );
313+ )-> type ;
313314 }
314315
315316 if ($ expr instanceof BinaryOp \NotEqual) {
@@ -1345,34 +1346,42 @@ public function getShiftRightType(Expr $left, Expr $right, callable $getTypeCall
13451346 return $ this ->resolveCommonMath (new Expr \BinaryOp \ShiftRight ($ left , $ right ), $ leftType , $ rightType );
13461347 }
13471348
1348- public function resolveIdenticalType (Type $ leftType , Type $ rightType ): BooleanType
1349+ /**
1350+ * @return TypeResult<BooleanType>
1351+ */
1352+ public function resolveIdenticalType (Type $ leftType , Type $ rightType ): TypeResult
13491353 {
13501354 if ($ leftType instanceof NeverType || $ rightType instanceof NeverType) {
1351- return new ConstantBooleanType (false );
1355+ return new TypeResult ( new ConstantBooleanType (false ), [] );
13521356 }
13531357
13541358 if ($ leftType instanceof ConstantScalarType && $ rightType instanceof ConstantScalarType) {
1355- return new ConstantBooleanType ($ leftType ->getValue () === $ rightType ->getValue ());
1359+ return new TypeResult ( new ConstantBooleanType ($ leftType ->getValue () === $ rightType ->getValue ()), [] );
13561360 }
13571361
13581362 $ leftTypeFiniteTypes = $ leftType ->getFiniteTypes ();
13591363 $ rightTypeFiniteType = $ rightType ->getFiniteTypes ();
13601364 if (count ($ leftTypeFiniteTypes ) === 1 && count ($ rightTypeFiniteType ) === 1 ) {
1361- return new ConstantBooleanType ($ leftTypeFiniteTypes [0 ]->equals ($ rightTypeFiniteType [0 ]));
1365+ return new TypeResult ( new ConstantBooleanType ($ leftTypeFiniteTypes [0 ]->equals ($ rightTypeFiniteType [0 ])), [] );
13621366 }
13631367
1364- if ($ leftType ->isSuperTypeOf ($ rightType )->no () && $ rightType ->isSuperTypeOf ($ leftType )->no ()) {
1365- return new ConstantBooleanType (false );
1368+ $ leftIsSuperTypeOfRight = $ leftType ->isSuperTypeOf ($ rightType );
1369+ $ rightIsSuperTypeOfLeft = $ rightType ->isSuperTypeOf ($ leftType );
1370+ if ($ leftIsSuperTypeOfRight ->no () && $ rightIsSuperTypeOfLeft ->no ()) {
1371+ return new TypeResult (new ConstantBooleanType (false ), array_merge ($ leftIsSuperTypeOfRight ->reasons , $ rightIsSuperTypeOfLeft ->reasons ));
13661372 }
13671373
13681374 if ($ leftType instanceof ConstantArrayType && $ rightType instanceof ConstantArrayType) {
1369- return $ this ->resolveConstantArrayTypeComparison ($ leftType , $ rightType , fn ($ leftValueType , $ rightValueType ): BooleanType => $ this ->resolveIdenticalType ($ leftValueType , $ rightValueType ));
1375+ return $ this ->resolveConstantArrayTypeComparison ($ leftType , $ rightType , fn ($ leftValueType , $ rightValueType ): TypeResult => $ this ->resolveIdenticalType ($ leftValueType , $ rightValueType ));
13701376 }
13711377
1372- return new BooleanType ();
1378+ return new TypeResult ( new BooleanType (), [] );
13731379 }
13741380
1375- public function resolveEqualType (Type $ leftType , Type $ rightType ): BooleanType
1381+ /**
1382+ * @return TypeResult<BooleanType>
1383+ */
1384+ public function resolveEqualType (Type $ leftType , Type $ rightType ): TypeResult
13761385 {
13771386 if (
13781387 ($ leftType ->isEnum ()->yes () && $ rightType ->isTrue ()->no ())
@@ -1382,16 +1391,17 @@ public function resolveEqualType(Type $leftType, Type $rightType): BooleanType
13821391 }
13831392
13841393 if ($ leftType instanceof ConstantArrayType && $ rightType instanceof ConstantArrayType) {
1385- return $ this ->resolveConstantArrayTypeComparison ($ leftType , $ rightType , fn ($ leftValueType , $ rightValueType ): BooleanType => $ this ->resolveEqualType ($ leftValueType , $ rightValueType ));
1394+ return $ this ->resolveConstantArrayTypeComparison ($ leftType , $ rightType , fn ($ leftValueType , $ rightValueType ): TypeResult => $ this ->resolveEqualType ($ leftValueType , $ rightValueType ));
13861395 }
13871396
1388- return $ leftType ->looseCompare ($ rightType , $ this ->phpVersion );
1397+ return new TypeResult ( $ leftType ->looseCompare ($ rightType , $ this ->phpVersion ), [] );
13891398 }
13901399
13911400 /**
1392- * @param callable(Type, Type): BooleanType $valueComparisonCallback
1401+ * @param callable(Type, Type): TypeResult<BooleanType> $valueComparisonCallback
1402+ * @return TypeResult<BooleanType>
13931403 */
1394- private function resolveConstantArrayTypeComparison (ConstantArrayType $ leftType , ConstantArrayType $ rightType , callable $ valueComparisonCallback ): BooleanType
1404+ private function resolveConstantArrayTypeComparison (ConstantArrayType $ leftType , ConstantArrayType $ rightType , callable $ valueComparisonCallback ): TypeResult
13951405 {
13961406 $ leftKeyTypes = $ leftType ->getKeyTypes ();
13971407 $ rightKeyTypes = $ rightType ->getKeyTypes ();
@@ -1408,7 +1418,7 @@ private function resolveConstantArrayTypeComparison(ConstantArrayType $leftType,
14081418
14091419 if (count ($ rightKeyTypes ) === 0 ) {
14101420 if (!$ leftOptional ) {
1411- return new ConstantBooleanType (false );
1421+ return new TypeResult ( new ConstantBooleanType (false ), [] );
14121422 }
14131423 continue ;
14141424 }
@@ -1421,13 +1431,13 @@ private function resolveConstantArrayTypeComparison(ConstantArrayType $leftType,
14211431 $ found = true ;
14221432 break ;
14231433 } elseif (!$ rightType ->isOptionalKey ($ j )) {
1424- return new ConstantBooleanType (false );
1434+ return new TypeResult ( new ConstantBooleanType (false ), [] );
14251435 }
14261436 }
14271437
14281438 if (!$ found ) {
14291439 if (!$ leftOptional ) {
1430- return new ConstantBooleanType (false );
1440+ return new TypeResult ( new ConstantBooleanType (false ), [] );
14311441 }
14321442 continue ;
14331443 }
@@ -1444,21 +1454,22 @@ private function resolveConstantArrayTypeComparison(ConstantArrayType $leftType,
14441454 }
14451455 }
14461456
1447- $ leftIdenticalToRight = $ valueComparisonCallback ($ leftValueTypes [$ i ], $ rightValueTypes [$ j ]);
1457+ $ leftIdenticalToRightResult = $ valueComparisonCallback ($ leftValueTypes [$ i ], $ rightValueTypes [$ j ]);
1458+ $ leftIdenticalToRight = $ leftIdenticalToRightResult ->type ;
14481459 if ($ leftIdenticalToRight ->isFalse ()->yes ()) {
1449- return new ConstantBooleanType ( false ) ;
1460+ return $ leftIdenticalToRightResult ;
14501461 }
14511462 $ resultType = TypeCombinator::union ($ resultType , $ leftIdenticalToRight );
14521463 }
14531464
14541465 foreach (array_keys ($ rightKeyTypes ) as $ j ) {
14551466 if (!$ rightType ->isOptionalKey ($ j )) {
1456- return new ConstantBooleanType (false );
1467+ return new TypeResult ( new ConstantBooleanType (false ), [] );
14571468 }
14581469 $ resultType = new BooleanType ();
14591470 }
14601471
1461- return $ resultType ->toBoolean ();
1472+ return new TypeResult ( $ resultType ->toBoolean (), [] );
14621473 }
14631474
14641475 private function callOperatorTypeSpecifyingExtensions (Expr \BinaryOp $ expr , Type $ leftType , Type $ rightType ): ?Type
0 commit comments