@@ -628,18 +628,7 @@ private function resolveType(Expr $node): Type
628
628
$ leftType = $ this ->getType ($ node ->left );
629
629
$ rightType = $ this ->getType ($ node ->right );
630
630
631
- $ stringType = new StringType ();
632
- $ integerType = new IntegerType ();
633
- $ floatType = new FloatType ();
634
- if (
635
- ($ stringType ->isSuperTypeOf ($ leftType )->yes () && $ stringType ->isSuperTypeOf ($ rightType )->yes ())
636
- || ($ integerType ->isSuperTypeOf ($ leftType )->yes () && $ integerType ->isSuperTypeOf ($ rightType )->yes ())
637
- || ($ floatType ->isSuperTypeOf ($ leftType )->yes () && $ floatType ->isSuperTypeOf ($ rightType )->yes ())
638
- ) {
639
- return $ this ->getType (new Expr \BinaryOp \Identical ($ node ->left , $ node ->right ));
640
- }
641
-
642
- return new BooleanType ();
631
+ return $ this ->resolveEqualType ($ leftType , $ rightType );
643
632
}
644
633
645
634
if ($ node instanceof Expr \BinaryOp \NotEqual) {
@@ -2335,7 +2324,7 @@ private function resolveType(Expr $node): Type
2335
2324
return new MixedType ();
2336
2325
}
2337
2326
2338
- private function resolveIdenticalType (Type $ leftType , Type $ rightType ): Type
2327
+ private function resolveIdenticalType (Type $ leftType , Type $ rightType ): BooleanType
2339
2328
{
2340
2329
$ isSuperset = $ leftType ->isSuperTypeOf ($ rightType );
2341
2330
if ($ isSuperset ->no ()) {
@@ -2350,65 +2339,93 @@ private function resolveIdenticalType(Type $leftType, Type $rightType): Type
2350
2339
}
2351
2340
2352
2341
if ($ leftType instanceof ConstantArrayType && $ rightType instanceof ConstantArrayType) {
2353
- $ leftValueTypes = $ leftType ->getValueTypes ();
2354
- $ rightKeyTypes = $ rightType ->getKeyTypes ();
2355
- $ rightValueTypes = $ rightType ->getValueTypes ();
2356
- $ hasOptional = false ;
2357
- foreach ($ leftType ->getKeyTypes () as $ i => $ keyType ) {
2358
- if (!array_key_exists ($ i , $ rightKeyTypes )) {
2359
- if ($ leftType ->isOptionalKey ($ i )) {
2360
- $ hasOptional = true ;
2361
- continue ;
2362
- }
2363
- return new ConstantBooleanType (false );
2364
- }
2342
+ return $ this ->resolveConstantArrayTypeComparison ($ leftType , $ rightType , fn ($ leftValueType , $ rightValueType ): BooleanType => $ this ->resolveIdenticalType ($ leftValueType , $ rightValueType ));
2343
+ }
2365
2344
2366
- $ rightKeyType = $ rightKeyTypes [$ i ];
2367
- if (!$ keyType ->equals ($ rightKeyType )) {
2368
- return new ConstantBooleanType (false );
2369
- }
2345
+ return new BooleanType ();
2346
+ }
2370
2347
2371
- $ leftValueType = $ leftValueTypes [$ i ];
2372
- $ rightValueType = $ rightValueTypes [$ i ];
2373
- $ leftIdenticalToRight = $ this ->resolveIdenticalType ($ leftValueType , $ rightValueType );
2374
- if ($ leftIdenticalToRight instanceof ConstantBooleanType) {
2375
- if (!$ leftIdenticalToRight ->getValue ()) {
2376
- return new ConstantBooleanType (false );
2377
- }
2378
- $ isLeftOptional = $ leftType ->isOptionalKey ($ i );
2379
- if ($ isLeftOptional || $ rightType ->isOptionalKey ($ i )) {
2380
- $ hasOptional = true ;
2381
- }
2382
- continue ;
2383
- }
2348
+ private function resolveEqualType (Type $ leftType , Type $ rightType ): BooleanType
2349
+ {
2350
+ $ stringType = new StringType ();
2351
+ $ integerType = new IntegerType ();
2352
+ $ floatType = new FloatType ();
2353
+ if (
2354
+ ($ stringType ->isSuperTypeOf ($ leftType )->yes () && $ stringType ->isSuperTypeOf ($ rightType )->yes ())
2355
+ || ($ integerType ->isSuperTypeOf ($ leftType )->yes () && $ integerType ->isSuperTypeOf ($ rightType )->yes ())
2356
+ || ($ floatType ->isSuperTypeOf ($ leftType )->yes () && $ floatType ->isSuperTypeOf ($ rightType )->yes ())
2357
+ ) {
2358
+ return $ this ->resolveIdenticalType ($ leftType , $ rightType );
2359
+ }
2384
2360
2385
- $ hasOptional = true ;
2386
- }
2361
+ if ($ leftType instanceof ConstantArrayType && $ rightType instanceof ConstantArrayType) {
2362
+ return $ this ->resolveConstantArrayTypeComparison ($ leftType , $ rightType , fn ($ leftValueType , $ rightValueType ): BooleanType => $ this ->resolveEqualType ($ leftValueType , $ rightValueType ));
2363
+ }
2387
2364
2388
- if (!isset ($ i )) {
2389
- $ i = 0 ;
2390
- } else {
2391
- $ i ++;
2392
- }
2365
+ return new BooleanType ();
2366
+ }
2393
2367
2394
- $ rightKeyTypesCount = count ($ rightKeyTypes );
2395
- for (; $ i < $ rightKeyTypesCount ; $ i ++) {
2396
- if ($ rightType ->isOptionalKey ($ i )) {
2368
+ /**
2369
+ * @param callable(Type, Type): BooleanType $valueComparisonCallback
2370
+ */
2371
+ private function resolveConstantArrayTypeComparison (ConstantArrayType $ leftType , ConstantArrayType $ rightType , callable $ valueComparisonCallback ): BooleanType
2372
+ {
2373
+ $ leftValueTypes = $ leftType ->getValueTypes ();
2374
+ $ rightKeyTypes = $ rightType ->getKeyTypes ();
2375
+ $ rightValueTypes = $ rightType ->getValueTypes ();
2376
+ $ hasOptional = false ;
2377
+ foreach ($ leftType ->getKeyTypes () as $ i => $ keyType ) {
2378
+ if (!array_key_exists ($ i , $ rightKeyTypes )) {
2379
+ if ($ leftType ->isOptionalKey ($ i )) {
2397
2380
$ hasOptional = true ;
2398
2381
continue ;
2399
2382
}
2383
+ return new ConstantBooleanType (false );
2384
+ }
2400
2385
2386
+ $ rightKeyType = $ rightKeyTypes [$ i ];
2387
+ if (!$ keyType ->equals ($ rightKeyType )) {
2401
2388
return new ConstantBooleanType (false );
2402
2389
}
2403
2390
2404
- if ($ hasOptional ) {
2405
- return new BooleanType ();
2391
+ $ leftValueType = $ leftValueTypes [$ i ];
2392
+ $ rightValueType = $ rightValueTypes [$ i ];
2393
+ $ leftIdenticalToRight = $ valueComparisonCallback ($ leftValueType , $ rightValueType );
2394
+ if ($ leftIdenticalToRight instanceof ConstantBooleanType) {
2395
+ if (!$ leftIdenticalToRight ->getValue ()) {
2396
+ return new ConstantBooleanType (false );
2397
+ }
2398
+ $ isLeftOptional = $ leftType ->isOptionalKey ($ i );
2399
+ if ($ isLeftOptional || $ rightType ->isOptionalKey ($ i )) {
2400
+ $ hasOptional = true ;
2401
+ }
2402
+ continue ;
2406
2403
}
2407
2404
2408
- return new ConstantBooleanType ( true ) ;
2405
+ $ hasOptional = true ;
2409
2406
}
2410
2407
2411
- return new BooleanType ();
2408
+ if (!isset ($ i )) {
2409
+ $ i = 0 ;
2410
+ } else {
2411
+ $ i ++;
2412
+ }
2413
+
2414
+ $ rightKeyTypesCount = count ($ rightKeyTypes );
2415
+ for (; $ i < $ rightKeyTypesCount ; $ i ++) {
2416
+ if ($ rightType ->isOptionalKey ($ i )) {
2417
+ $ hasOptional = true ;
2418
+ continue ;
2419
+ }
2420
+
2421
+ return new ConstantBooleanType (false );
2422
+ }
2423
+
2424
+ if ($ hasOptional ) {
2425
+ return new BooleanType ();
2426
+ }
2427
+
2428
+ return new ConstantBooleanType (true );
2412
2429
}
2413
2430
2414
2431
private function resolveConcatType (Expr \BinaryOp \Concat |Expr \AssignOp \Concat $ node ): Type
0 commit comments