|
20 | 20 | use PHPStan\Type\TypeTraverser; |
21 | 21 | use PHPStan\Type\UnionType; |
22 | 22 | use Rector\NodeTypeResolver\PHPStan\Type\TypeFactory; |
| 23 | +use Rector\NodeTypeResolver\PHPStan\TypeHasher; |
23 | 24 | use Rector\StaticTypeMapper\StaticTypeMapper; |
24 | 25 |
|
25 | 26 | final readonly class TypeNormalizer |
|
32 | 33 | public function __construct( |
33 | 34 | private TypeFactory $typeFactory, |
34 | 35 | private StaticTypeMapper $staticTypeMapper, |
35 | | - private ArrayTypeLeastCommonDenominatorResolver $arrayTypeLeastCommonDenominatorResolver |
| 36 | + private ArrayTypeLeastCommonDenominatorResolver $arrayTypeLeastCommonDenominatorResolver, |
| 37 | + private TypeHasher $typeHasher |
36 | 38 | ) { |
37 | 39 |
|
38 | 40 | } |
@@ -94,7 +96,41 @@ public function generalizeConstantTypes(Type $type): Type |
94 | 96 | if ($type instanceof UnionType) { |
95 | 97 | $generalizedUnionedTypes = []; |
96 | 98 | foreach ($type->getTypes() as $unionedType) { |
97 | | - $generalizedUnionedTypes[] = $this->generalizeConstantTypes($unionedType); |
| 99 | + $generalizedUnionedType = $this->generalizeConstantTypes($unionedType); |
| 100 | + |
| 101 | + if ($generalizedUnionedType instanceof ArrayType) { |
| 102 | + $keyType = $this->typeHasher->createTypeHash($generalizedUnionedType->getKeyType()); |
| 103 | + |
| 104 | + foreach ($generalizedUnionedTypes as $key => $existingUnionedType) { |
| 105 | + if (! $existingUnionedType instanceof ArrayType) { |
| 106 | + continue; |
| 107 | + } |
| 108 | + |
| 109 | + $existingKeyType = $this->typeHasher->createTypeHash( |
| 110 | + $existingUnionedType->getKeyType() |
| 111 | + ); |
| 112 | + |
| 113 | + if ($keyType !== $existingKeyType) { |
| 114 | + continue; |
| 115 | + } |
| 116 | + |
| 117 | + $uniqueTypes = $this->typeFactory->uniquateTypes( |
| 118 | + [$existingUnionedType->getItemType(), $generalizedUnionedType->getItemType()] |
| 119 | + ); |
| 120 | + |
| 121 | + if (count($uniqueTypes) !== 1) { |
| 122 | + continue; |
| 123 | + } |
| 124 | + |
| 125 | + $generalizedUnionedTypes[$key] = new ArrayType( |
| 126 | + $existingUnionedType->getKeyType(), |
| 127 | + $uniqueTypes[0] |
| 128 | + ); |
| 129 | + continue 2; |
| 130 | + } |
| 131 | + } |
| 132 | + |
| 133 | + $generalizedUnionedTypes[] = $generalizedUnionedType; |
98 | 134 | } |
99 | 135 |
|
100 | 136 | $uniqueGeneralizedUnionTypes = $this->typeFactory->uniquateTypes($generalizedUnionedTypes); |
|
0 commit comments